thecodex.expert · The Codex Family of Knowledge
Language Reference

Java

Write once, run anywhere — statically typed, JVM-powered, the backbone of enterprise software for 30 years.

Language Reference Java 25 LTS · Java 26 current Static typing Last verified:
New to Java? This is the reference encyclopedia — dip in anytime. To learn step by step, start the Java Course →
Canonical Definition

Java is a statically typed, class-based, object-oriented programming language that compiles to platform-independent bytecode executed by the Java Virtual Machine (JVM), providing automatic memory management, true multi-threading, and a comprehensive standard library — the dominant language for enterprise software and Android development.

📑 Java Reference — All Topics

Variables & Types

Primitives, reference types, boxing, autoboxing, var.

OOP

Classes, inheritance, interfaces, abstract classes, polymorphism.

Collections & Generics

List, Map, Set, Queue, generics, iterators.

Exceptions

Checked vs unchecked, try/catch/finally, multi-catch.

Streams & Lambdas

Functional interfaces, stream pipeline, filter/map/reduce.

Concurrency

Threads, synchronized, ExecutorService, CompletableFuture.

What is Java

Compiles to bytecode, not machine code — write once, run on any JVM.

Setup and JDK

JDK, JRE, JVM — only one of the three lets you actually compile code.

Control Flow

The modern switch expression makes the classic fall-through bug impossible.

Methods

No standalone functions exist — every method lives inside a class, always.

Classes and Objects

static means one shared copy; every other field is per-object.

Inheritance and Polymorphism

A parent-typed reference calls the CHILD's override — the reference type doesn't decide.

Interfaces and Abstract Classes

A class extends one class, but implements as many interfaces as it wants.

Records

One line replaces 40+ lines of constructor, getters, equals, and hashCode.

Sealed Classes

permits names every class allowed to extend it — finalized in Java 17.

Pattern Matching

instanceof used to require a redundant manual cast — not anymore.

Annotations

@Override adds zero bytes to the running program — it exists purely for the compiler.

Reflection

How Spring finds your @Autowired constructors without ever seeing your source.

IO and NIO

Reading a whole file used to take a loop and a BufferedReader — now it's one line.

String Handling

== on strings is a classic bug — identical content, different objects.

Packages and Modules

Before Java 9, 'public' meant visible from anywhere on the classpath, period.

Javadoc

Every official Java API page was generated from comments in the JDK's own source.

Testing

JUnit 6 (2025) is current — eight years after JUnit 5, now needing Java 17+.

Build Tools

Maven's build file is XML with no logic; Gradle's is an actual program.

Garbage Collection

G1 or ZGC — Java lets you pick a genuinely different collector for the job.

JVM Internals

Code starts interpreted, then the JIT compiles the hot paths to native code live.

Optional and Null Safety

Makes 'might be absent' explicit in a signature — but null still exists everywhere else.

Enums

A real class — can have constructors, fields, and even per-constant method bodies.

Standard Library

java.time replaced the old Date class entirely, but Java never deletes anything.

Virtual Threads

A platform thread is expensive; a virtual thread is so cheap you can run millions.

One sentence

Java is the language that made "write once, run anywhere" real — compile your code once to bytecode, run it on any machine with a JVM, making it the backbone of enterprise software and Android apps for three decades.

What Java is

Java is a statically typed, class-based, object-oriented, compiled-to-bytecode programming language created by James Gosling at Sun Microsystems and released in 1995. Java compiles source code to platform-independent bytecode that runs on the Java Virtual Machine (JVM). The JVM is available on virtually every platform — Windows, Linux, macOS, mainframes, embedded systems — fulfilling the "write once, run anywhere" promise. Java is the language of choice for large enterprise systems, Android apps (via Android Runtime), and backend services used by billions of people.

JavaHello.java
// Every Java program needs a class; filename must match class name
public class Hello {

    // Entry point: must be exactly this signature
    public static void main(String[] args) {
        System.out.println("Hello, World!");

        // Variables — types are explicit
        int count = 10;
        double price = 29.99;
        boolean active = true;
        String name = "Priya";  // String is a class, not a primitive

        // String formatting
        System.out.printf("Hello %s, price: %.2f%n", name, price);
        System.out.println("Count: " + count);  // implicit toString()
    }
}

Primitives vs. objects

Java has two categories of values. Primitive types: byte, short, int, long, float, double, char, boolean. These are not objects — they are raw values stored on the stack or inline in arrays. Reference types: everything else. Objects, arrays, and strings are reference types — variables hold references (pointers) to heap-allocated objects, not the objects themselves.

Autoboxing: Java automatically wraps primitives in their wrapper classes (intInteger, doubleDouble) when needed — e.g. when storing in a List<Integer>. This is transparent but has a performance cost.

JavaTypes.java
// Primitives — stored by value
int x = 42;
double pi = 3.14;
boolean flag = true;
char letter = 'A';

// Reference types — stored as pointer to heap object
String s = "hello";        // immutable
int[] arr = {1, 2, 3, 4}; // array is an object

// Autoboxing — automatic primitive ↔ wrapper conversion
List<Integer> list = new ArrayList<>();
list.add(42);       // autoboxes int 42 to Integer(42)
int val = list.get(0); // unboxes back to int

// null — only valid for reference types, not primitives
String name = null;   // valid
// int n = null;      // compile error

Classes and OOP

JavaBankAccount.java
public class BankAccount {
    // Instance fields
    private final String owner;   // final = immutable after init
    private double balance;

    // Constructor
    public BankAccount(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

    // Instance methods
    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");
        balance += amount;
    }

    public double getBalance() { return balance; }   // getter

    @Override
    public String toString() {
        return String.format("Account(%s: %.2f)", owner, balance);
    }
}

// Usage
BankAccount acc = new BankAccount("Priya", 1000.0);
acc.deposit(500.0);
System.out.println(acc);   // Account(Priya: 1500.00)

Generics and collections

Java's Collections Framework provides List, Map, Set, Queue, and more, all generic — the type parameter specifies what they hold. The most used: ArrayList<T> (dynamic array), HashMap<K,V> (hash map), HashSet<T> (hash set), LinkedList<T>, TreeMap<K,V> (sorted map).

JavaCollections.java
import java.util.*;

// Generic collections
List<String> names = new ArrayList<>();
names.add("Priya");
names.add("Rahul");
names.sort(Comparator.naturalOrder());

Map<String, Integer> scores = new HashMap<>();
scores.put("Priya", 95);
scores.put("Rahul", 88);
System.out.println(scores.get("Priya")); // 95

// Streams (Java 8+) — functional-style operations
List<String> filtered = names.stream()
    .filter(n -> n.startsWith("P"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());
// ["PRIYA"]

Exception handling

Java has checked and unchecked exceptions. Checked exceptions must be declared in the method signature (throws) or caught — compile error otherwise. IOException, SQLException. Unchecked exceptions extend RuntimeException — no declaration needed. NullPointerException, IllegalArgumentException. The finally block runs regardless; try-with-resources (Java 7+) automatically closes AutoCloseable resources.

JavaExceptions.java
// Try-with-resources — automatically closes reader
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    System.err.println("File not found: " + e.getMessage());
} catch (IOException e) {
    System.err.println("IO error: " + e.getMessage());
}
// reader.close() called automatically — even if exception thrown

The JVM, JIT compilation, and GC

The JVM (Java Virtual Machine) is a stack-based virtual machine that executes Java bytecode. It provides: automatic memory management (garbage collection), JIT compilation (HotSpot compiles hot bytecode to native machine code), platform independence, and runtime security. The HotSpot JIT uses tiered compilation: first interpret bytecode (Tier 0), then compile with the C1 (client) compiler (fast, Tier 1-3), then the C2 (server) compiler with aggressive optimisations for hot methods (Tier 4). This gives fast startup and high peak performance.

Generics: type erasure

Java generics use type erasure: generic type parameters are checked at compile time but removed at runtime. At runtime, List<String> and List<Integer> are both just List. This means: you cannot do new T() or instanceof List<String> at runtime. The erasure decision was made for backward compatibility with pre-generics Java (Java 5 introduced generics in 2004). Kotlin and C# chose reified generics (kept at runtime) — a cleaner model.

JavaGenerics.java
// Generic method
public static <T extends Comparable<T>> T max(T a, T b) {
    return a.compareTo(b) > 0 ? a : b;
}

// Bounded wildcards
public static double sum(List<? extends Number> list) {
    return list.stream().mapToDouble(Number::doubleValue).sum();
}
// Accepts List<Integer>, List<Double>, etc.

// Type erasure — both are the same class at runtime
List<String> strings = new ArrayList<>();
List<Integer> ints = new ArrayList<>();
System.out.println(strings.getClass() == ints.getClass()); // true

Concurrency: threads and the java.util.concurrent package

Java has true multi-threading — threads run in parallel on multiple CPU cores, unlike Python's GIL. The java.util.concurrent package (added in Java 5) provides high-level concurrency utilities: ExecutorService (thread pools), Future<V>/CompletableFuture<V> (async computation), Lock/ReentrantLock (finer-grained than synchronized), ConcurrentHashMap, BlockingQueue.

Java 21 introduced virtual threads (Project Loom, JEP 444): lightweight JVM-managed threads that don't map 1:1 to OS threads. Virtual threads enable millions of concurrent I/O operations without the memory cost of OS threads (~1MB each). Platform threads are mapped to OS threads; virtual threads are multiplexed on a pool of carrier (platform) threads.

JavaConcurrency.java
import java.util.concurrent.*;

// Thread pool
ExecutorService pool = Executors.newFixedThreadPool(4);
Future<Integer> future = pool.submit(() -> {
    // computation on background thread
    return 42;
});
int result = future.get(); // blocks until complete

// CompletableFuture — composable async
CompletableFuture.supplyAsync(() -> fetchUser(1))
    .thenApply(user -> user.getName())
    .thenAccept(name -> System.out.println("User: " + name));

// Virtual threads (Java 21+)
Thread.ofVirtual().start(() -> System.out.println("Virtual thread!"));
// Can create millions — each uses only ~KB of heap

Modern Java: records, sealed classes, pattern matching

VersionFeatureWhat it does
Java 8 (2014)Lambdas, Streams, OptionalFunctional-style operations; null safety
Java 9 (2017)Module system (Jigsaw)Strong encapsulation at the JAR level
Java 14 (2020)Records (preview)Immutable data classes with auto-generated constructor, equals, hashCode
Java 16 (2021)Records (stable), instanceof patternrecord Point(int x, int y) {}
Java 17 (2021)Sealed classes, text blocksRestrict which classes can extend a class
Java 21 (2023)Virtual threads, pattern matching switchProject Loom; exhaustive switch
Java 23 (2024)Unnamed classes (preview), Markdown docsNo-boilerplate entry points
Commonly confused
Java and JavaScript are completely unrelated. Java is a statically typed, compiled-to-JVM language. JavaScript is dynamically typed and runs in browsers. The name similarity was pure marketing by Netscape in 1995 to capitalise on Java's popularity.
Primitives and their wrapper classes behave differently. int is a value; Integer is an object. == on two Integer objects compares references, not values — Integer.valueOf(127) == Integer.valueOf(127) is true (cached) but Integer.valueOf(200) == Integer.valueOf(200) is false. Always use .equals() to compare objects.
Java generics are erased at runtime. You cannot check instanceof List<String> at runtime, nor create new T() inside a generic method. Both fail because the type parameter is gone after compilation. Use Class<T> tokens or reflection when runtime type information is needed.

JVM bytecode and the class file format

A Java .class file contains: a magic number (0xCAFEBABE), major/minor version numbers, a constant pool (strings, class references, method signatures), access flags, field/method descriptors, and the bytecode instructions for each method. The bytecode instruction set has ~200 opcodes: iload/istore (load/store int from stack frame), invokevirtual (virtual method dispatch), invokestatic (static method call), new/dup/invokespecial (object creation). The javap -c ClassName command disassembles bytecode.

Java Memory Model

The Java Memory Model (JLS §17) defines the happens-before relationship: actions in thread A happen-before all actions in thread B that observe their effects. Key rules: (1) program order — each action in a thread happens-before all subsequent actions in that thread; (2) monitor lock — an unlock happens-before every subsequent lock of the same monitor; (3) volatile — a write to a volatile variable happens-before every subsequent read of that variable. Without a happens-before relationship, there is no guarantee a thread sees another thread's writes — even on a modern CPU with cache coherency protocols. The JMM is formally defined in JLS §17.4.

Project Loom: virtual thread implementation

Virtual threads (JEP 444, Java 21) are implemented as continuations — resumable computations. When a virtual thread blocks on I/O, the JVM parks the continuation (saves its stack to heap memory) and frees the carrier thread for other virtual threads. When the I/O completes, the continuation is resumed on any available carrier thread. The carrier thread pool defaults to the number of CPU cores. This allows millions of virtual threads to coexist with only a small fixed number of OS threads — solving the C10k problem at the JVM level without async/await syntax changes.

Specification reference

Gosling, J., Joy, B., Steele, G., Bracha, G. & Buckley, A. (2021). The Java Language Specification, Java SE 17 Edition. Oracle. docs.oracle.com/javase/specs/jls/se17/html/. JEP 444 — Virtual Threads (Java 21). openjdk.org/jeps/444. Bloch, J. (2018). Effective Java (3rd ed.). Addison-Wesley.

Sources

1
Gosling, J. et al. (2021). The Java Language Specification, Java SE 17 Edition. Oracle. docs.oracle.com/javase/specs/.
2
Bloch, J. (2018). Effective Java (3rd ed.). Addison-Wesley. — Authoritative Java best practices.
3
JEP 444 — Virtual Threads (Java 21). openjdk.org/jeps/444.
4
Oracle. Java Platform, Standard Edition Documentation. docs.oracle.com/en/java/javase/.
5
Goetz, B. et al. (2006). Java Concurrency in Practice. Addison-Wesley.
Source confidence: High Last verified: Primary source: Java Language Specification — docs.oracle.com/javase/specs/