1. 8 Primitive Data Types
Java defines eight primitive data types. They are predefined by the language and named by a reserved keyword. Primitives represent raw values and do not share state like objects do. They can be broken down into four distinct categories:
Primitive Specifications Matrix
| Data Type | Size | Default Value | Range / Value Definition |
|---|---|---|---|
byte |
1 byte (8 bits) | 0 |
-128 to 127 |
short |
2 bytes (16 bits) | 0 |
-32,768 to 32,767 |
int |
4 bytes (32 bits) | 0 |
-231 to 231-1 (~2 Billion) |
long |
8 bytes (64 bits) | 0L |
-263 to 263-1 |
float |
4 bytes (32 bits) | 0.0f |
Up to 6-7 decimal digits of precision |
double |
8 bytes (64 bits) | 0.0d |
Up to 15 decimal digits of precision |
char |
2 bytes (16 bits) | '\u0000' |
Single Unicode character (0 to 65,535) |
boolean |
Virtual Machine Dependent | false |
true or false only |
2. Primitive Data Types vs. Wrapper Types
A wrapper class is a class that encapsulates (wraps) a primitive data type into an object
Comparison Matrix
| Feature | Primitive Type | Wrapper Class |
|---|---|---|
| Examples | int, char, double, boolean |
Integer, Character, Double, Boolean |
| Memory Allocation | Stored directly on the Stack | Stored as objects on the Heap |
| Nullability | Cannot be null (Defaults to 0, false, etc.) |
Can be null (Leads to NullPointerException if not handled) |
| Methods | No methods associated with them | Contains utility methods (e.g., Integer.parseInt()) |
float), whereas wrapper classes start with an uppercase letter because they are actual classes (e.g., Float).
3. Type Casting in Java
Type casting is assigning a value of one primitive data type to another type. In Java, casting is broadly split into two types based on memory size and precision data loss.
A. Widening Casting (Implicit Conversion)
Done automatically by Java when passing a smaller data type to a larger data type size. There is no data loss.
byte → short → char → int → long → float → double
public class WideningExample {
public static void main(String[] args) {
int myInt = 9;
double myDouble = myInt; // Automatic casting: int to double
System.out.println(myInt); // Outputs 9
System.out.println(myDouble); // Outputs 9.0
}
}
B. Narrowing Casting (Explicit Conversion)
Must be done manually by placing the type in parentheses in front of the value. This can cause data loss or precision truncation.
double → float → long → int → char → short → byte
public class NarrowingExample {
public static void main(String[] args) {
double myDouble = 9.78d;
int myInt = (int) myDouble; // Manual casting: double to int
System.out.println(myDouble); // Outputs 9.78
System.out.println(myInt); // Outputs 9 (Fractional part is lost!)
}
}
4. Autoboxing and Unboxing
To eliminate boilerplates, the Java compiler automates the conversion between primitives and wrappers. This feature was introduced in Java 5.
Autoboxing
The automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. (e.g., converting an int to an Integer).
public class AutoboxingExample {
public static void main(String[] args) {
int primitiveInt = 25;
// Autoboxing (Modern Java automatically handles this)
Integer modernWay = primitiveInt;
}
}
Unboxing
The automatic conversion of wrapper types back to their corresponding primitive types (e.g., converting an Integer to an int).
public class UnboxingExample {
public static void main(String[] args) {
Integer objectInteger = new Integer(100);
// Unboxing (Modern Java)
int modernWay = objectInteger;
System.out.println("Value: " + modernWay);
}
}