2.1 The Eight Primitive Data Types & Literal Values

Key Takeaways

  • Java defines exactly eight primitive types: byte, short, int, long, float, double, char, and boolean, storing raw values directly on the stack without object overhead.
  • Non-decimal integer literals default to 32-bit int; literals exceeding 2,147,483,647 require an explicit L or l suffix to compile as 64-bit long values.
  • Floating-point literals default to 64-bit double; assigning a decimal literal to a 32-bit float requires an explicit F or f suffix to prevent compiler conversion errors.
  • char is a 16-bit unsigned Unicode numeric type (0 to 65,535), while boolean represents pure logical truth (true or false) and cannot be cast to or from any numeric type.
  • Class and instance member fields automatically receive default initialization values (0, 0.0, false, '\u0000', null), whereas local variables receive no default values and fail compilation if read before definite assignment.
Last updated: September 2026

2.1 The Eight Primitive Data Types & Literal Values

Quick Summary: Java partitions all data into primitive types and reference types. The eight primitives (byte, short, int, long, float, double, char, boolean) store raw binary values directly on the call stack for maximum runtime efficiency. Integer literals default to 32-bit int, floating-point literals default to 64-bit double, and char represents 16-bit unsigned Unicode characters. While object and class fields receive automatic default values upon allocation, local variables declared within methods receive no default value and fail compilation if read before explicit initialization.


1. The Primitive vs. Reference Distinction

In Java, every variable declaration binds an identifier to a specific, immutable data type. Java's type system is bifurcated into two distinct categories:

  1. Primitive Types: Built directly into the core Java language specification. A primitive variable reserves a fixed number of bits in memory and stores its raw binary data value directly in that memory slot (typically on the thread call stack). Primitives have no methods, cannot be invoked with the dot (.) operator, possess no internal object header overhead, and can never hold the value null.
  2. Reference Types: Built upon classes, interfaces, or arrays (such as java.lang.String, java.util.Scanner, or int[]). A reference variable does not hold object data directly; instead, it stores a memory address (pointer) that refers to an object located on the garbage-collected Java heap.
STACK MEMORY                               HEAP MEMORY
+-----------------------+                  +---------------------------+
| primitive: int age=25 |                  |                           |
| (Holds raw value 25)  |                  |                           |
+-----------------------+                  |                           |
| reference: String name| ---------------> | String Object ("Alice")   |
| (Holds heap address)  |                  | (Object header, char[])   |
+-----------------------+                  +---------------------------+

Understanding this physical separation is foundational for Exam 1Z0-811: primitive variables represent pure data, whereas reference variables represent handles pointing to objects.


2. Comprehensive Breakdown of the Eight Primitive Types

Java provides exactly eight primitive data types. They are classified into four integer types, two floating-point types, one character type, and one boolean type.

TypeClassificationWidthByte SizeValue Range (Inclusive)Default Field ValueLiteral Example
byteSigned Integer8 bits1 byte-128 to 127 (-2^7 to 2^7 - 1)0(byte) 100
shortSigned Integer16 bits2 bytes-32,768 to 32,767 (-2^15 to 2^15 - 1)0(short) 5000
intSigned Integer32 bits4 bytes-2,147,483,648 to 2,147,483,647042
longSigned Integer64 bits8 bytes-9,223,372,036,854,775,808 to 9,223,372,036,854,775,8070L5000000000L
floatFloating-Point32 bits4 bytesIEEE 754 (±1.4E-45 to ±3.4028235E+38)0.0f3.14159F
doubleFloating-Point64 bits8 bytesIEEE 754 (±4.9E-324 to ±1.7976931348623157E+308)0.0d2.71828
charUnsigned Unicode16 bits2 bytes0 to 65,535 ('\u0000' to '\uffff')'\u0000''A', '\u0041'
booleanLogical TruthJVM dep.JVM dep.true or falsefalsetrue, false

The Four Signed Integer Types

All integer types in Java are signed, utilizing two's complement binary representation. Java has no unsigned modifier for primitive declarations.

  • byte (8-bit) and short (16-bit) are primarily used for low-level stream I/O, binary file structures, or large memory arrays where conserving heap space is paramount.
  • int (32-bit) is the default standard type for all integer computations in Java. Modern CPU architectures are optimized for 32-bit and 64-bit math.
  • long (64-bit) is required when values exceed roughly 2.14 billion, commonly used for high-precision timestamps, financial transaction identifiers, and large counter metrics.

The Two Floating-Point Types

Java conforms strictly to the IEEE 754 standard for binary floating-point arithmetic.

  • float (32-bit single precision): Provides roughly 6 to 7 decimal digits of precision. Because decimal literals default to double, assigning a decimal number to a float without an F or f suffix causes a compilation error.
  • double (64-bit double precision): Provides roughly 15 to 17 decimal digits of precision. It is the default type for all floating-point expressions and numeric literals with decimal points in Java.

Exam Watch: Neither float nor double should ever be used for exact monetary or financial calculations due to binary floating-point rounding errors (e.g., 0.1 + 0.2 does not equal 0.3 exactly). For precise currency, commercial Java applications use java.math.BigDecimal.


3. Integral Literals & Alternate Number Systems

A literal is the source code representation of a fixed value. In Java, any whole number written directly into code (such as 10, 0, -500) is automatically assigned the primitive type int by the compiler.

The long Literal Suffix (L / l)

Because whole numbers default to 32-bit int, if you write a numeric literal that exceeds the maximum int value (2,147,483,647), the compiler issues an immediate syntax error unless you explicitly inform it that the literal is a 64-bit long:

// COMPILE ERROR: integer number too large: 3000000000
long distanceToMars = 3000000000;

// CORRECT: Append 'L' to declare a 64-bit long literal
long distanceToMars = 3000000000L;

Always use the uppercase L suffix. While the lowercase l is grammatically legal, it looks virtually indistinguishable from the digit 1 in standard programming fonts (e.g., 50l looks like 501).

Alternate Radix Representations

Java supports integer literals expressed in four distinct numeral systems:

int decimalVal     = 26;        // Base 10: Standard digits 0-9 (no prefix)
int octalVal       = 032;       // Base 8:  Digits 0-7, preceded by leading zero '0'
int hexVal         = 0x1A;      // Base 16: Digits 0-9, A-F, preceded by '0x' or '0X'
int binaryVal      = 0b11010;   // Base 2:  Digits 0-1, preceded by '0b' or '0B'

// All four variables evaluate to the exact same numerical quantity: 26
System.out.println(decimalVal == octalVal);  // prints true
System.out.println(hexVal == binaryVal);     // prints true

Exam Trap: Beware of leading zeros! Writing int code = 053; does not store decimal 53; it stores octal 5 * 8^1 + 3 * 8^0 = 43. Furthermore, writing int err = 089; triggers a compile error because digits 8 and 9 are invalid in base 8.


4. Character & Boolean Primitive Details

The char Primitive: Unsigned 16-Bit Unicode

Unlike languages where a char is an 8-bit ASCII value, Java was designed from the ground up for internationalization. A Java char is a 16-bit unsigned integer representing UTF-16 code units with a numerical range from 0 to 65,535 (0x0000 to 0xFFFF).

  • Character literals must be enclosed in single quotes ('Z'), whereas String literals use double quotes ("Z").
  • Because char is fundamentally an unsigned numeric type, you can assign integers or Unicode hexadecimal escapes directly to a char variable:
char c1 = 'A';         // Standard character literal
char c2 = 65;          // Decimal Unicode code point for 'A'
char c3 = '\u0041';    // 4-digit hexadecimal Unicode escape sequence for 'A'

System.out.println(c1 == c2); // prints true
System.out.println(c2 == c3); // prints true

Common character escape sequences:

  • '\n' : Linefeed / newline
  • '\t' : Horizontal tab
  • '\'' : Single quote character
  • '\"' : Double quote character
  • '\\' : Backslash character

The boolean Primitive: Isolated Truth Values

A boolean variable holds only one of two literal values: true or false.

CRITICAL EXAM RULE: In Java, boolean values have no numeric equivalence. Unlike C or C++, true does NOT equal 1, and false does NOT equal 0. You cannot convert, cast, or compare integers and booleans. Statements such as if (1) or boolean flag = (boolean) 0; fail compilation immediately.


5. Underscores in Numeric Literals (Java 7+)

To make large numeric literals readable to human developers, Java permits placing underscore characters (_) between digits.

int oneMillion        = 1_000_000;          // Much easier to read than 1000000
long creditCardNumber = 4532_8910_1234_5678L;
float piApprox        = 3.14_15_92F;
int hexBytes          = 0xFF_EC_00_12;
int binaryNibbles     = 0b1101_0110_0010_1111;

Strict Restrictions on Underscore Placement (Exam Traps)

The compiler strictly enforces that underscores may only appear between adjacent digits. The following placements are compile-time syntax errors:

  1. At the start or end of a literal:
    int bad1 = _52;   // ERROR: parsed as an identifier name, not a literal!
    int bad2 = 52_;   // ERROR: illegal underscore at end of literal
    
  2. Adjacent to a decimal point:
    float bad3 = 3._14F; // ERROR: underscore adjacent to decimal point
    float bad4 = 3_.14F; // ERROR: underscore adjacent to decimal point
    
  3. Adjacent to type suffixes (L, F, D):
    long bad5 = 999_L;   // ERROR: underscore adjacent to 'L' suffix
    float bad6 = 5.0_F;  // ERROR: underscore adjacent to 'F' suffix
    
  4. Adjacent to radix prefixes (0x, 0b):
    int bad7 = 0_x52;    // ERROR: underscore inside radix prefix
    int bad8 = 0x_52;    // ERROR: underscore immediately following radix prefix
    int bad9 = 0b_1010;  // ERROR: underscore immediately following radix prefix
    

6. Field Default Values vs. Uninitialized Local Variables

A critical objective on Exam 1Z0-811 is understanding where default values are assigned and where they are omitted.

+------------------------------------+-------------------------------------+
|      Class & Instance Fields       |           Local Variables           |
+------------------------------------+-------------------------------------+
| Declared inside class body         | Declared inside a method, loop,     |
| (static fields or instance fields) | constructor, or block parameter     |
| Allocated on the Heap              | Allocated on the Stack Frame        |
| Automatically given DEFAULT values | NEVER given default values          |
| Safe to read without assignment    | COMPILE ERROR if read uninitialized |
+------------------------------------+-------------------------------------+

Automatic Default Values for Fields

When an object is instantiated or a class is loaded, the JVM automatically initializes all member fields to predefined defaults:

  • byte, short, int, long -> 0
  • float, double -> 0.0f / 0.0d
  • char -> '\u0000' (the null character, integer value 0)
  • boolean -> false
  • All reference types (String, arrays, custom objects) -> null

The Definite Assignment Rule for Local Variables

Local variables live on stack frames. Allocating and zeroing stack memory for every method call would impose substantial performance degradation. Consequently, Java does not initialize local variables.

A local variable can be declared without an initial value, but the compiler enforces definite assignment: if there is any theoretical path through your code where a local variable might be read before receiving an explicit value, compilation fails:

public class InitializationDemo {
    int instanceCounter; // Field: automatically initialized to 0
    boolean isReady;     // Field: automatically initialized to false

    public void compute() {
        int localTotal;  // Local variable: uninitialized
        
        System.out.println(instanceCounter); // COMPILES: prints 0
        System.out.println(isReady);         // COMPILES: prints false
        
        // System.out.println(localTotal);   // COMPILE ERROR: variable localTotal might not have been initialized
    }
}

Even if an assignment occurs inside a conditional statement, the compiler flags an error if the condition cannot be proven true at compile time:

public void conditionalInit(boolean condition) {
    int x;
    if (condition) {
        x = 100;
    }
    // If condition is false, x was never assigned!
    // System.out.println(x); // COMPILE ERROR: variable x might not have been initialized
}
Loading diagram...
Hierarchy and Characteristics of Java Primitive Types
Test Your Knowledge

Which of the following numeric literal declarations compiles successfully without errors?

A
B
C
D
Test Your Knowledge

Consider the following Java class definition:

public class TestScope {
    int score;
    boolean active;

    public void evaluate() {
        int count;
        if (score == 0) {
            count = 10;
        }
        System.out.println(score);
        System.out.println(active);
        System.out.println(count);
    }
}
What occurs when an attempt is made to compile this code?

A
B
C
D
Test Your Knowledge

Which statement accurately describes the characteristics and behavioral constraints of Java primitive types?

A
B
C
D