Java Data Types - Complete Guide
Introduction to Java Data Types
Data types in Java define the kind of values that can be stored in variables and how much memory they require. Java is a strongly typed language, so each variable must be declared with a data type before use. This enforces type safety and reduces errors.
Java data types are grouped into two main categories: primitive types and non-primitive (reference) types. Understanding both is essential for writing correct and efficient programs.
Primitive vs Non-Primitive Data Types
Java divides its data types into primitives, which are built into the language, and non-primitives, which are created using classes.
Feature | Primitive Types | Non-Primitive Types |
---|---|---|
Definition | Predefined by Java | Created by programmer (classes, objects) |
Storage | Stored directly in stack memory | Reference stored in stack, object in heap |
Default Value | Default values like 0, 0.0, false, '\u0000' | Default is null |
Size | Fixed size depending on type | Variable size depending on object |
Examples | byte, short, int, long, float, double, char, boolean | String, Arrays, Classes, Interfaces |
The 8 Primitive Data Types
Java provides eight primitive types that are the foundation of data representation.
public class PrimitiveTypes {
public static void main(String[] args) {
byte small = 100; // 8-bit, -128 to 127
short medium = 10000; // 16-bit, -32,768 to 32,767
int number = 1000000; // 32-bit, -2^31 to 2^31-1
long big = 10000000000L; // 64-bit, -2^63 to 2^63-1
float price = 19.99f; // 32-bit, ~7 decimal digits
double pi = 3.1415926535; // 64-bit, ~15 decimal digits
char grade = 'A'; // 16-bit Unicode character
boolean active = true; // true or false
System.out.println("Byte: " + small);
System.out.println("Short: " + medium);
System.out.println("Int: " + number);
System.out.println("Long: " + big);
System.out.println("Float: " + price);
System.out.println("Double: " + pi);
System.out.println("Char: " + grade);
System.out.println("Boolean: " + active);
}
}
Byte: 100 Short: 10000 Int: 1000000 Long: 10000000000 Float: 19.99 Double: 3.1415926535 Char: A Boolean: true
Default Values of Primitive Types
Instance variables of primitive types are automatically initialized with default values when not explicitly set. Local variables, however, must be initialized before use.
public class DefaultValues {
byte defaultByte;
short defaultShort;
int defaultInt;
long defaultLong;
float defaultFloat;
double defaultDouble;
char defaultChar;
boolean defaultBoolean;
public static void main(String[] args) {
DefaultValues dv = new DefaultValues();
System.out.println("Default byte: " + dv.defaultByte);
System.out.println("Default short: " + dv.defaultShort);
System.out.println("Default int: " + dv.defaultInt);
System.out.println("Default long: " + dv.defaultLong);
System.out.println("Default float: " + dv.defaultFloat);
System.out.println("Default double: " + dv.defaultDouble);
System.out.println("Default char: " + (int)dv.defaultChar);
System.out.println("Default boolean: " + dv.defaultBoolean);
}
}
Default byte: 0 Default short: 0 Default int: 0 Default long: 0 Default float: 0.0 Default double: 0.0 Default char: 0 Default boolean: false
Type Conversion and Casting
Java supports type conversion between primitives. Widening (implicit) conversion happens automatically when assigning a smaller type to a larger type. Narrowing (explicit) conversion requires casting and may lose data.
public class TypeConversion {
public static void main(String[] args) {
int intValue = 100;
long longValue = intValue; // widening
double doubleValue = intValue; // widening
double precise = 9.87;
int approx = (int) precise; // narrowing, decimal truncated
char letter = 'A';
int code = letter; // char to int
System.out.println("Double: " + precise + ", Cast to int: " + approx);
System.out.println("Char: " + letter + ", Code: " + code);
float nan = Float.NaN;
float infinity = Float.POSITIVE_INFINITY;
System.out.println("NaN: " + nan);
System.out.println("Infinity: " + infinity);
}
}
Double: 9.87, Cast to int: 9 Char: A, Code: 65 NaN: NaN Infinity: Infinity
Best Practices for Data Types
- ✅ Use the smallest type that fits the value range
- ✅ Prefer int for integer math unless a wider range is needed
- ✅ Use double for general floating-point calculations
- ✅ Cast explicitly when narrowing types
- ✅ Mark constants with final for clarity
- ✅ Use wrapper classes when objects are required (e.g., in collections)
- ✅ Watch out for overflow/underflow with numeric types
- ✅ Choose meaningful variable names reflecting purpose