Java Primitive Data Types: Sizes, Ranges and Defaults
Java has eight primitive types: byte, short, int, long, float, double, char and boolean. Their sizes, ranges, default values and literals, and when to use each.
- Course: Java study plan
- Module: Types & operators
- Kind: Lesson
- Reading time: 14 min
- Runtime: OpenJDK 18
What are the primitive data types in Java?
Java has eight primitive data types: byte, short, int and long for whole numbers of 8, 16, 32 and 64 bits, float and double for floating-point numbers, char for a 16-bit UTF-16 code unit, and boolean for true or false. Their sizes are the same on every JVM, and every other type in Java is a reference type.
Lesson
Java has exactly eight primitive types, and there will never be a ninth. Everything else — every class, array, enum, record, interface — is a reference type. Knowing the eight cold, including their sizes, ranges and literal syntax, is the foundation of every numeric bug you will ever debug.
The table to memorise
| Type | Size | Range | Default | Literal |
|---|---|---|---|---|
byte | 8-bit signed | −128 … 127 | 0 | (byte) 7 |
short | 16-bit signed | −32 768 … 32 767 | 0 | (short) 7 |
int | 32-bit signed | −2 147 483 648 … 2 147 483 647 | 0 | 7 |
long | 64-bit signed | ±9.22 × 10¹⁸ | 0L | 7L |
float | 32-bit IEEE 754 | ~±3.4 × 10³⁸, ~7 significant digits | 0.0f | 7.0f |
double | 64-bit IEEE 754 | ~±1.8 × 10³⁰⁸, ~15–16 significant digits | 0.0 | 7.0 |
char | 16-bit unsigned | 0 … 65 535 (UTF-16 code unit) | '\u0000' | 'A' |
boolean | 1 bit of information (size unspecified) | true / false | false | true |
Two numbers worth knowing by heart: Integer.MAX_VALUE is 2 147 483 647 (about 2.1 billion — a phone number or a file size in bytes can exceed it), and Long.MAX_VALUE is 9 223 372 036 854 775 807 (about 9.2 quintillion). All integral types are signed two's complement; there is no unsigned int in Java, though Integer.toUnsignedString and friends exist for when you need to interpret bits that way.
The defaults matter only for fields (and array elements). A local variable has no default: reading it before assignment is a compile error, not a zero.
Integer literals
int decimal = 42;
int hex = 0x2A; // 42
int binary = 0b101010; // 42 (Java 7+)
int octal = 052; // 42 — a leading zero means octal; a classic trap
long big = 3_000_000_000L; // underscores anywhere between digits
int million = 1_000_000;
A plain integer literal is an int. 3000000000 without the L is a compile error ("integer number too large") because it does not fit in an int. The suffix can be lower-case l but never write it — 3000000000l looks like 30000000001.
Underscores are for readability only and are removed by the compiler; they cannot start or end a literal or sit next to the 0x/0b prefix or the L suffix.
Floating-point literals
double d = 3.14; // double by default
float f = 3.14f; // the f is required; 3.14 alone is a double and will not fit
double e = 1e-9; // scientific notation
double h = 0x1.8p1; // hexadecimal floating point: 1.5 × 2¹ = 3.0 (rare)
float f = 3.14; fails with "possible lossy conversion from double to float". Use double unless you have a measured reason (graphics, huge arrays) to use float.
char: a number in disguise
char c = 'A'; // 65
char d = 65; // also 'A' — an int constant that fits
char e = '\u0041'; // Unicode escape, also 'A'
char nl = '\n'; // escapes: \n \t \r \\ \' \" \0 \b \f
int code = c; // 65, widening
char next = (char) (c + 1); // 'B' — c + 1 is an int, so the cast is needed
char is unsigned 16-bit and arithmetic on it yields int. 'a' + 1 is 98, not 'b'. The classic use in interviews:
int digitValue = ch - '0'; // '7' → 7
int letterIndex = ch - 'a'; // 'c' → 2
char upper = (char) (ch - 'a' + 'A');
Since Java is UTF-16, a char is a code unit, not necessarily a whole character — an emoji is two chars. Module 3 returns to this.
boolean: not a number
Unlike C, boolean does not convert to or from integers. if (x) where x is an int is a compile error; write if (x != 0). true and false are the only values, and Boolean.parseBoolean("TRUE") is how you get one from text (anything but a case-insensitive "true" is false).
Why primitives exist at all
Java's designers wanted "everything is an object" but measured the cost: an int in a register is one machine word and one instruction to add; an Integer object is a heap allocation, a header, a pointer indirection, and garbage-collector work. For loops, arrays and arithmetic — the hot paths of every program — primitives are the difference between fast and unusable. The compromise is the eight primitives plus the wrapper classes (Integer, Double, …) for when an object is required, with autoboxing converting between them (a later lesson, and a rich source of bugs).
A consequence you feel constantly: generics cannot hold primitives. List<int> is a compile error; it must be List<Integer>. int[] on the other hand is a real array of primitives, contiguous and fast.
Choosing a type
- Counting, indexing, most arithmetic →
int. - Anything that can reach billions — timestamps in milliseconds, file sizes, money in the smallest unit, products of two
ints →long. - Measurements and science →
double. Never money (Module 2, lesson 5). byteandshortare for arrays of them (binary data, memory-tight structures), not for "small numbers": arithmetic on them promotes tointanyway.floatonly for graphics APIs or huge datasets where memory halves.
Sizes are guaranteed
In C, int is "at least 16 bits" and varies by platform. In Java, int is 32 bits everywhere — the same .class file computes the same result on every JVM. This is part of the portability promise and why Java arithmetic is specified down to overflow behaviour (next lessons).
Interview angle
- "What is the size of
boolean?" Unspecified by the language; HotSpot uses one byte in fields and arrays. - "Is
charsigned?" No — it is the only unsigned primitive. - "What does
0.1f == 0.1give?"false: thefloatis widened to adouble, and the two roundings of 0.1 differ. - "Why is
int i = 3_000_000_000;an error?" The literal exceedsInteger.MAX_VALUE; it needsLand along.
Key takeaways
- Eight primitives: four integral (
byte,short,int,long), two floating (float,double),char,boolean. Fixed sizes everywhere. - Integer literals are
intunless suffixedL; decimal literals aredoubleunless suffixedf. charis an unsigned 16-bit number; arithmetic on it givesint.booleannever converts to a number. Fields default to zero/false/null; locals have no default.
Common questions
What is the maximum value of int in Java?
Integer.MAX_VALUE is 2,147,483,647, about 2.1 billion, because int is a 32-bit signed two's complement number. Values that can go beyond it, such as timestamps in milliseconds or file sizes in bytes, need a long, whose maximum is 9,223,372,036,854,775,807.
What is the size of boolean in Java?
The Java language does not specify it: a boolean holds one bit of information, true or false. HotSpot, the common JVM, uses one byte for a boolean field or array element. Unlike in C, a boolean never converts to or from a number.
What are the default values of primitive types in Java?
Fields and array elements default to 0 for the integral types, 0.0 for float and double, the character with code 0 for char, and false for boolean. Local variables have no default: reading one before it is assigned is a compile error.
Why does Java have primitive types if everything is an object?
For speed. An int is one machine word that adds in a single instruction, while an Integer is a heap object with a header, a pointer to follow and garbage-collector work. Wrapper classes and autoboxing cover the places an object is required, such as List<Integer>.
Is char signed or unsigned in Java?
char is the only unsigned primitive: a 16-bit value from 0 to 65,535 holding one UTF-16 code unit. Arithmetic on a char yields an int, so 'a' + 1 is 98, and ch - '0' turns a digit character into its value.
Exercises
The smallest type that fits
Read an integer n, then n whole numbers (each fits in a long). For each, print the smallest integral type that can hold it: byte, short, int or long.
Use the MIN_VALUE/MAX_VALUE constants of the wrapper classes rather than typing the ranges.
Input: n, then n numbers. Output: n lines.
Example: 3 then 100 40000 -129 →
byte
int
shortBits of an int
Read an integer n and n int values. For each print <x>: bin=<Integer.toBinaryString> hex=<Integer.toHexString> ones=<Integer.bitCount> sign=<negative|non-negative>. Negative numbers show their two's-complement pattern — thirty-two bits, most of them ones.
Example: 3 then 5 -1 255 →
5: bin=101 hex=5 ones=2 sign=non-negative
-1: bin=11111111111111111111111111111111 hex=ffffffff ones=32 sign=negative
255: bin=11111111 hex=ff ones=8 sign=non-negativeIn this module: Types & operators
← Checkpoint — Java & the JVM · Variables, constants and var →