Java Language Specification — Data Types Source: https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html 1. Spec Reference JLS Chapter 4 : Types, Values, and Variables — https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html JLS §4.1 : The Kinds of Types and Values JLS §4.2 : Primitive Types and Values JLS §4.2.1 : Integral Types and Values JLS §4.2.2 : Integer Operations JLS §4.2.3 : Floating-Point Types, Formats, and Values JLS §4.2.4 : Floating-Point Operations JLS §4.2.5 : The boolean Type and boolean Values JLS §4.3 : Reference Types and Values JLS §4.3.1 : Objects JLS §4.3.2 : The Class Object JLS §4.3.3 : The Class String JLS §4.3.4 : When Reference Types Are the Same JLS §4.4 : Type Variables JLS §4.5 : Parameterized Types JLS §4.8 : Raw Types JLS §4.9 : Intersection Types JLS §4.10 : Subtyping JLS §4.12 : Variables -- JLS §4.1: Types --
Type:
PrimitiveType
ReferenceType
-- JLS §4.2: Primitive Types --
PrimitiveType:
{Annotation} NumericType
{Annotation} boolean
NumericType:
IntegralType
FloatingPointType
IntegralType: one of
byte short int long char
FloatingPointType: one of
float double
-- JLS §4.3: Reference Types --
ReferenceType:
ClassOrInterfaceType
TypeVariable
ArrayType
ClassOrInterfaceType:
ClassType
InterfaceType
ClassType:
{Annotation} TypeIdentifier [TypeArguments]
PackageName . {Annotation} TypeIdentifier [TypeArguments]
ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments]
InterfaceType:
ClassType
TypeVariable:
{Annotation} TypeIdentifier
ArrayType:
PrimitiveType Dims
ClassOrInterfaceType Dims
TypeVariable Dims
Dims:
{Annotation} [ ] {{Annotation} [ ]}
-- JLS §4.4: Type Variables --
TypeParameter:
{TypeParameterModifier} TypeIdentifier [TypeBound]
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
AdditionalBound:
& InterfaceType
-- JLS §4.5: Parameterized Types --
TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument { , TypeArgument }
TypeArgument:
ReferenceType
Wildcard
Wildcard:
{Annotation} ? [WildcardBounds]
WildcardBounds:
extends ReferenceType
super ReferenceType
-- JLS §3.10: Literals (associated with types) --
IntegerLiteral:
DecimalIntegerLiteral
HexIntegerLiteral
OctalIntegerLiteral
BinaryIntegerLiteral
FloatingPointLiteral:
DecimalFloatingPointLiteral
HexadecimalFloatingPointLiteral
BooleanLiteral:
true
false
NullLiteral:
null
3. Core Rules & Constraints 3.1 Primitive Type Sizes (JLS §4.2) Type Width Min Value Max Value Default byte 8-bit signed -128 127 0 short 16-bit signed -32,768 32,767 0 int 32-bit signed two's complement -2^31 2^31 - 1 0 long 64-bit signed two's complement -2^63 2^63 - 1 0L float 32-bit IEEE 754 ~1.4E-45 ~3.4E+38 0.0f double 64-bit IEEE 754 ~4.9E-324 ~1.8E+308 0.0d char 16-bit unsigned Unicode '\u0000' (0) '\uFFFF' (65535) '\u0000' boolean JVM-dependent size false true false
3.2 boolean Type (JLS §4.2.5) Only two values: true and false. boolean is NOT a numeric type; cannot be cast to/from numeric types. In arrays: JVM may represent each boolean as 1 byte. Boolean.parseBoolean("TRUE") returns true (case-insensitive for "true"). 3.3 char Type (JLS §4.2.1) Represents a single 16-bit Unicode code unit (UTF-16). Supplementary characters (code points > U+FFFF) require two char values (a surrogate pair). char is an unsigned numeric type; it can participate in arithmetic. char widening: char → int → long → float → double (JLS §5.1.2). 3.4 Reference Types (JLS §4.3) Reference types include class types, interface types, array types, and type variables. Default value for any reference type is null. null is not an instance of any type, but is assignable to any reference type. Two reference type variables are equal (==) only if they refer to the same object. 3.5 Type Compatibility and Subtyping (JLS §4.10) Every class type is a subtype of Object. An array type T[] is a subtype of Object, Cloneable, and Serializable. If S is a subtype of T, then S[] is a subtype of T[] (array covariance — JLS §4.10.3). Covariance is a potential source of ArrayStoreException at runtime. 4. Type Rules 4.1 Widening and Narrowing (JLS §5.1) Widening primitive conversions (no explicit cast needed): byte → short → int → long → float → double char → int → long → float → double Narrowing requires explicit cast and may lose information. byte and short are widened to int before arithmetic operations. 4.2 Floating-Point Special Values (JLS §4.2.3) IEEE 754 defines: positive infinity, negative infinity, NaN, positive zero, negative zero. NaN != NaN is true (the only value not equal to itself). 0.0 == -0.0 is true. Double.isNaN(), Double.isInfinite() for checks. Float.NaN, Double.NaN, Float.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY are constants. 4.3 Integer Overflow (JLS §4.2.2) Integer arithmetic is modular (two's complement wraparound). Integer.MAX_VALUE + 1 == Integer.MIN_VALUE — no exception thrown. Use Math.addExact() etc. for overflow-checked arithmetic (Java 8+). 4.4 Generic Types and Erasure (JLS §4.5, §4.8) Generic type parameters are erased at compile time. List<String> and List<Integer> are both List at runtime. Cannot use instanceof with parameterized types: obj instanceof List<String> is a compile error. Raw types (List without type arg) generate unchecked warnings. 4.5 Array Types (JLS §10.1) new int[n] creates an array of n ints, each initialized to 0. Array length is final after creation; stored in length field. array.length is not a method call; it is a field access (JLS §10.7). Multi-dimensional arrays are arrays of arrays: int[][] grid = new int[3][4]. 5. Behavioral Specification 5.1 Integer Operations (JLS §4.2.2) Division by zero: int x = 5 / 0; → throws ArithmeticException. Modulo by zero: int x = 5 % 0; → throws ArithmeticException. Shift operators: <<, >>, >>> use only the 5 low-order bits of the RHS for int (6 bits for long). 1 << 33 is same as 1 << 1 = 2 (33 mod 32 = 1). Unsigned right shift >>> fills with zeros (sign bit not extended). 5.2 Floating-Point Operations (JLS §4.2.4) 1.0 / 0.0 → Double.POSITIVE_INFINITY (no exception). 0.0 / 0.0 → Double.NaN. Math.sqrt(-1.0) → Double.NaN. Floating-point results are rounded to nearest, ties to even (IEEE 754 default mode). strictfp (obsolete Java 17+) enforced IEEE 754 strict evaluation; now default everywhere. 5.3 null Reference Behavior (JLS §4.1) Dereferencing null throws NullPointerException. Java 14+ NPEs include helpful null-detail messages (JEP 358). null instanceof T always returns false without throwing. 5.4 String Interning (JLS §3.10.5) String literals are interned — all references to "hello" point to the same String object. new String("hello") creates a new object (not interned by default). String.intern() returns the canonical interned version. 6. Defined vs Undefined Behavior Situation Behavior per JLS Integer division by zero ArithmeticException thrown (JLS §15.17.2) Floating-point division by zero Returns infinity or NaN (JLS §4.2.3) Integer overflow Silent wraparound (two's complement) NaN == NaN false (always, per IEEE 754) null == null true null instanceof Foo false (JLS §15.20.2) Array access out of bounds ArrayIndexOutOfBoundsException Negative array size NegativeArraySizeException char arithmetic Promoted to int; result is int not char long literal without L > int range Compile-time error
7. Edge Cases from Spec 7.1 Integer Shift Edge Cases int x = 1 ;
System . out . println ( x << 32 ); // == 1 (32 mod 32 == 0, not 0!)
System . out . println ( x << 33 ); // == 2 (33 mod 32 == 1)
long y = 1L ;
System . out . println ( y << 64 ); // == 1L (64 mod 64 == 0)
7.2 char as Integer char c = 'A' ; // 65
int i = c + 1 ; // 66 (int, not char)
char next = ( char )( c + 1 ); // 'B' — explicit cast back to char
System . out . println ( 'a' + 'b' ); // prints 195 (int arithmetic)
7.3 Floating-Point Precision System . out . println ( 0.1 + 0.2 ); // 0.30000000000000004 (IEEE 754)
System . out . println ( 0.1f + 0.2f ); // 0.3 (float rounds differently)
System . out . println ( 1.0 / 0.0 ); // Infinity
System . out . println ( - 1.0 / 0.0 ); // -Infinity
System . out . println ( 0.0 / 0.0 ); // NaN
System . out . println ( Double . NaN == Double . NaN ); // false
7.4 Negative Zero double nz = - 0.0 ;
double pz = 0.0 ;
System . out . println ( nz == pz ); // true
System . out . println ( 1.0 / nz ); // -Infinity
System . out . println ( 1.0 / pz ); // +Infinity
7.5 Array Covariance Trap String [] strings = new String [ 3 ] ;
Object [] objects = strings ; // legal at compile time (covariance)
objects [ 0 ] = new Integer ( 42 ); // compiles but throws ArrayStoreException at runtime
7.6 boolean Is Not Numeric // boolean cannot be compared with 0 or 1
boolean b = true ;
// if (b == 1) { } // COMPILE ERROR: incompatible types
// int n = b ? 1 : 0; // OK — ternary operator
8. Version History Java Version Change JEP/Reference Java 1.0 All 8 primitive types defined; Object, arrays JLS 1st ed. Java 5 Autoboxing/unboxing; generics with type erasure JSR 14, JSR 201 Java 5 Enhanced for loop over arrays and Iterable JSR 201 Java 7 Binary literals (0b101); underscores in literals JLS §3.10.1 Java 8 Integer.parseUnsignedInt(), Long.compareUnsigned() JDK-8 API Java 9 var in limited contexts (not data type per se) — Java 10 var for local variable type inference JEP 286 Java 14 Helpful NullPointerException messages JEP 358 Java 15 Text blocks: String with multiline literal JEP 378 Java 16 Records: transparent data carrier types JEP 395 Java 17 strictfp obsolete (IEEE 754 default everywhere) JEP 306 Java 21 Pattern matching for switch (standard) JEP 441
9. Implementation-Specific Behavior (JVM-Specific) 9.1 boolean in JVM JVM Spec §2.3.4: boolean has no dedicated bytecode type. boolean arrays use baload/bastore (byte instructions). boolean values are represented as int 0 (false) and 1 (true) in most contexts. On modern 64-bit JVMs, double operations are not significantly slower than float. float saves memory in arrays (4 bytes vs 8 bytes per element). Avoid mixing float and double arithmetic — implicit widening occurs. 9.3 Integer Caching Integer.valueOf(n) caches instances for values -128 to 127 (JLS §5.1.7, autoboxing). new Integer(n) always creates a new object (deprecated Java 9+). This makes Integer.valueOf(127) == Integer.valueOf(127) true, but Integer.valueOf(128) == Integer.valueOf(128) potentially false. 9.4 String Pool HotSpot JVM maintains a string pool (interned strings) in the Heap (moved from PermGen in Java 8). String literals are automatically interned at load time. String.intern() can place any string in the pool. 10. Spec Compliance Checklist 11. Official Examples (Compilable Java 21 Code) // Example 1: Primitive Type Ranges
// File: PrimitiveTypes.java
public class PrimitiveTypes {
public static void main ( String [] args ) {
// Integer types
byte b = Byte . MAX_VALUE ; // 127
short s = Short . MAX_VALUE ; // 32767
int i = Integer . MAX_VALUE ; // 2147483647
long l = Long . MAX_VALUE ; // 9223372036854775807
// Floating-point types
float f = Float . MAX_VALUE ; // ~3.4028235E38
double d = Double . MAX_VALUE ; // ~1.7976931348623157E308
// char
char c = Character . MAX_VALUE ; // '\uFFFF' = 65535
System . out . println ( "char max: " + ( int ) c );
// boolean
boolean flag = true ;
// Binary and hex literals (Java 7+)
int binary = 0b1010_1010 ; // 170
int hex = 0xFF_00_FF ; // 16711935
long bigNum = 1_000_000_000L ; // 1 billion
System . out . println ( "binary: " + binary );
System . out . println ( "hex: " + hex );
System . out . println ( "bigNum: " + bigNum );
}
}
// Example 2: Floating-Point Special Values
// File: FloatingPointEdges.java
public class FloatingPointEdges {
public static void main ( String [] args ) {
// IEEE 754 special values
double posInf = Double . POSITIVE_INFINITY ; // 1.0/0.0
double negInf = Double . NEGATIVE_INFINITY ; // -1.0/0.0
double nan = Double . NaN ; // 0.0/0.0
double negZero = - 0.0 ;
System . out . println ( "1.0 / 0.0 = " + ( 1.0 / 0.0 )); // Infinity
System . out . println ( "-1.0 / 0.0 = " + ( - 1.0 / 0.0 )); // -Infinity
System . out . println ( "0.0 / 0.0 = " + ( 0.0 / 0.0 )); // NaN
System . out . println ( "NaN == NaN: " + ( nan == nan )); // false
System . out . println ( "isNaN: " + Double . isNaN ( nan )); // true
System . out . println ( "-0.0 == 0.0: " + ( negZero == 0.0 )); // true
System . out . println ( "1/-0.0: " + ( 1.0 / negZero )); // -Infinity
System . out . println ( "Infinity + 1: " + ( posInf + 1 )); // Infinity
System . out . println ( "Infinity - Infinity: " + ( posInf - posInf )); // NaN
}
}
// Example 3: Integer Overflow and Checked Arithmetic
// File: IntegerOverflow.java
public class IntegerOverflow {
public static void main ( String [] args ) {
// Silent overflow (wraparound)
int maxInt = Integer . MAX_VALUE ;
System . out . println ( maxInt + 1 ); // -2147483648 (wraps!)
// Checked arithmetic (Java 8+)
try {
int result = Math . addExact ( Integer . MAX_VALUE , 1 );
} catch ( ArithmeticException e ) {
System . out . println ( "Overflow detected: " + e . getMessage ());
}
// Unsigned operations (Java 8+)
int unsignedMax = - 1 ; // all bits set = max unsigned value
System . out . println ( Integer . toUnsignedString ( unsignedMax )); // 4294967295
System . out . println ( Integer . compareUnsigned ( - 1 , 1 )); // positive (−1 > 1 unsigned)
}
}
// Example 4: Reference Types and Null
// File: ReferenceTypes.java
import java.util.List ;
import java.util.ArrayList ;
public class ReferenceTypes {
public static void main ( String [] args ) {
// null is the default reference
String s = null ;
System . out . println ( s instanceof String ); // false (not an NPE)
// Helpful NPE messages (Java 14+, JEP 358)
try {
String str = null ;
int len = str . length (); // NPE with detail message
} catch ( NullPointerException e ) {
System . out . println ( "NPE: " + e . getMessage ());
}
// Array covariance
String [] strings = { "a" , "b" };
Object [] objects = strings ; // widening — OK at compile time
try {
objects [ 0 ] = 42 ; // ArrayStoreException at runtime
} catch ( ArrayStoreException e ) {
System . out . println ( "ArrayStoreException: " + e . getMessage ());
}
// Generic type erasure
List < String > strList = new ArrayList <> ();
List < Integer > intList = new ArrayList <> ();
System . out . println ( strList . getClass () == intList . getClass ()); // true — same raw type
}
}
// Example 5: char Arithmetic and Unicode
// File: CharTypes.java
public class CharTypes {
public static void main ( String [] args ) {
char a = 'A' ;
char z = 'z' ;
// char arithmetic produces int
int diff = z - a ;
System . out . println ( "z - A = " + diff ); // 57
// Casting back to char
char next = ( char )( a + 1 );
System . out . println ( "A + 1 = " + next ); // B
// Unicode supplementary character (requires two chars)
String emoji = "\uD83D\uDE00" ; // Grinning face U+1F600
System . out . println ( "Emoji length: " + emoji . length ()); // 2 (two char code units)
System . out . println ( "Emoji codePointCount: " +
emoji . codePointCount ( 0 , emoji . length ())); // 1
// char as unsigned integer
char max = '\uFFFF' ;
System . out . println ( "char max as int: " + ( int ) max ); // 65535
// Iterating code points (handles supplementary chars)
"Hello\uD83D\uDE00" . codePoints ()
. forEach ( cp -> System . out . printf ( "U+%04X " , cp ));
System . out . println ();
}
}
Section Topic URL JLS §4 Types, Values, Variables https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html JLS §5 Conversions and Contexts https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html JLS §10 Arrays https://docs.oracle.com/javase/specs/jls/se21/html/jls-10.html JLS §15.17 Multiplicative Operators (division by zero) https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.17 JVMS §2.3 Primitive Types https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-2.html#jvms-2.3 JVMS §2.4 Reference Types https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-2.html#jvms-2.4 JEP 358 Helpful NullPointerExceptions https://openjdk.org/jeps/358 JEP 395 Records https://openjdk.org/jeps/395 JEP 441 Pattern Matching for switch https://openjdk.org/jeps/441
In this topic