Java has eight primitive types, and they hold raw values rather than references to objects. Four are whole-number types: byte (8 bits), short (16 bits), int (32 bits) and long (64 bits), all signed. Two are floating-point types: float (32 bits) and double (64 bits). char is a 16-bit unsigned value that stores a UTF-16 code unit, so it can be used in arithmetic, and boolean holds only true or false. Unlike some languages, a Java boolean is never a number: if (1) does not compile.
A literal is a value written directly in source code. A plain whole number such as 42 is an int literal, so a value too big for int needs the L suffix: long big = 3_000_000_000L; compiles, but the same number without L is a compile error even though the target is a long. A number with a decimal point, such as 3.14, is a double literal, so float f = 3.14; fails and you must write 3.14f or cast it. Character literals use single quotes ('A', '\n', '\u0041').
Whole-number literals can be written in four bases. Decimal is the default. A leading 0 means octal (017 is 15), 0x or 0X means hexadecimal (0x1F is 31), and 0b or 0B means binary (0b101 is 5). The octal rule is a classic trap: 010 is 8, not 10, and 09 does not compile because 9 is not an octal digit.
Underscores can separate digits for readability, as in 1_000_000 or 0b1010_0101. The rule is that an underscore must sit between two digits. So these are illegal: a leading or trailing underscore (_100, 100_), an underscore next to a decimal point (1_.5, 1._5), one right before a suffix (10_L, 2.0_f) and one straight after the 0x or 0b prefix (0x_FF). Several underscores in a row are fine (1__000), and so is one after the leading zero of an octal literal (0_17), because that zero counts as a digit.
Default values apply only to fields (instance and static variables) and to array elements. Numeric fields default to zero (0, 0L, 0.0f, 0.0), char to '\u0000', boolean to false, and every reference type to null. Local variables never get a default. Reading a local variable before it has definitely been assigned is a compile error, which the exam likes to hide inside an if branch.
int[] nums = new int[3]; // {0, 0, 0}
boolean[] flags = new boolean[2]; // {false, false}
int x;
// System.out.println(x); // does not compile: x not initialized
int hex = 0xFF, oct = 010, bin = 0b11;
System.out.println(hex + oct + bin); // 255 + 8 + 3 = 266
Key terms
- Primitive type
- One of the eight built-in value types (byte, short, int, long, float, double, char, boolean) that are not objects.
- Literal
- A fixed value written in source code, such as 42, 3.5f, 'x' or 0b1010.
- Octal literal
- A whole-number literal with a leading 0, read in base 8, so 010 equals 8.
- Default value
- The value a field or array element gets automatically: 0, false, '\u0000' or null. Local variables have none.
A payments service stores amounts in cents as a long. A developer writes long limit = 5_000_000_000; and the build fails, because the literal is still an int literal and is out of range. Adding L (5_000_000_000L) fixes it, and the underscores keep the number readable in code review.
Check yourself
Does float price = 9.99; compile?
No. 9.99 is a double literal, and assigning a double to a float is a narrowing conversion. Write 9.99f or cast with (float).
What does System.out.println(012 + 0x10); print?
26. 012 is octal for 10 and 0x10 is hexadecimal for 16.
Which of these is legal: 1_000, _1000, 0x_10, 1000_L?
Only 1_000. The others put an underscore at the start, right after the 0x prefix, or right before the L suffix.