Java data types
Every variable in Java has a type. Types fall into two broad groups:
1. Primitives (stored directly on the stack or inside
objects)
2. Reference types (variables hold a reference/pointer
to an object on the
heap).
Primitive types (always on stack)
Language provides these. They cannot be
null.
Type | Size (bytes) | Range / values
---------|--------------|------------------------------------------
byte | 1 (signed) | -128 to 127
short | 2 (signed) | -32,768 to 32,767
int | 4 (signed) | -2^31 to 2^31 - 1 (~±2.1 billion)
long | 8 (signed) | -2^63 to 2^63 - 1
float | 4 (IEEE 754) | ~±3.4 × 10^38 (6–7 decimal digits)
double | 8 (IEEE 754) | ~±1.7 × 10^308 (15 decimal digits)
boolean | JVM-defined | true or false only
char | 2 (UTF-16) | '\u0000' to '\uffff' (single Unicode code unit)
Reference Variables
String, arrays, classes you define, enums, records, interfaces, and
everything from the JDK (List, LocalDate,
etc.). They can be null and are garbage-collected on the
heap. See Garbage Collection.
String
String is a final class in java.lang, not a
primitive. String literals are immutable — any method that "changes" a
string returns a new object.
String a = "test";
String b = "test1";
a.length(); // 4
a.compareTo(b); // negative (a comes before b lexicographically)
a.equals(b); // false
a.equalsIgnoreCase("TEST"); // true
System.out.println(a.toUpperCase()); // TEST
System.out.println(a.substring(1, 3)); // es
Wrapper classes (Always allocated on heap)
A wrapper class is a class that encapsulates (wraps) a primitive data
type into an object.
Every primitive type in Java has a corresponding wrapper class in the
java.lang package (e.g., int becomes Integer, double becomes Double,
char becomes Character).
Why Primitives types are wrapped in Objects?
By wrapping a primitive inside an object, it gains object-like
capabilities, such as having methods, holding null values.
Java collections (like ArrayList, HashMap, etc.) and generics
only work with objects, not primitives. You cannot write
ArrayList<int>, but you can write ArrayList<Integer>.
Arrays
Arrays are reference types that hold a fixed number of elements of the same type. Length is set at creation and cannot grow.
int[] nums = { 1, 2, 3, 4, 5 };
String[] names = new String[3];
names[0] = "Alice";
names[1] = "Bob";
System.out.println(nums.length); // 5
System.out.println(nums[2]); // 3
// Multi-dimensional
int[][] matrix = { { 1, 2 }, { 3, 4 } };
Classes & Objects
Objects generally lie on heap but not all.
JVM uses Escape Analysis to keep some Objects on stack
Enums
Enums define a fixed set of named constants. They are type-safe alternatives to integer or string constants.
enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
Day today = Day.MON;
Day tomorrow = Day.valueOf("TUE");
if (today == Day.MON) {
System.out.println("Start of week");
}
for (Day d : Day.values()) {
System.out.println(d);
}
Records (Java 16+)
Records are compact, immutable data carriers. The compiler generates
constructor, accessors, equals, hashCode, and
toString automatically.
record Point(int x, int y) {}
Point origin = new Point(0, 0);
Point p = new Point(3, 4);
System.out.println(p.x()); // 3 (accessor, not getX())
System.out.println(p); // Point[x=3, y=4]
Common JDK types
Beyond collections, the JDK provides specialized reference types for math, time, and optional values.
Type | Package | Typical use
----------------|------------------|----------------------------------
BigInteger | java.math | Arbitrary-precision integers
BigDecimal | java.math | Exact decimal arithmetic (money)
LocalDate | java.time | Date without time zone (2026-07-18)
LocalDateTime | java.time | Date + time without zone
Instant | java.time | UTC timestamp (epoch-based)
ZonedDateTime | java.time | Date-time with time zone
UUID | java.util | 128-bit unique identifier
Optional<T> | java.util | Explicit nullable wrapper
Pattern | java.util.regex | Compiled regular expression
StringBuilder | java.lang | Mutable string builder
Special cases
void — not a variable type. Used only as a
method return type meaning "returns nothing".
public void printHello() {
System.out.println("Hello");
}
null — the default value for uninitialized
reference-type fields. Assigning null to a primitive is a
compile error.
String s = null; // OK — reference type
// int n = null; // compile error — primitive
var (Java 10+) — local type inference. The
compiler deduces the type; it is not a new datatype.
var message = "Hello"; // inferred as String
var numbers = List.of(1, 2, 3); // inferred as List<Integer>
Generics — parameterized types such as
List<T> and Map<K, V> let
collections and classes work with type-safe element types at compile
time.