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
Primitives, reference types, boxing, autoboxing, var.
Classes, inheritance, interfaces, abstract classes, polymorphism.
List, Map, Set, Queue, generics, iterators.
Checked vs unchecked, try/catch/finally, multi-catch.
Functional interfaces, stream pipeline, filter/map/reduce.
Threads, synchronized, ExecutorService, CompletableFuture.
Compiles to bytecode, not machine code — write once, run on any JVM.
JDK, JRE, JVM — only one of the three lets you actually compile code.
The modern switch expression makes the classic fall-through bug impossible.
No standalone functions exist — every method lives inside a class, always.
static means one shared copy; every other field is per-object.
A parent-typed reference calls the CHILD's override — the reference type doesn't decide.
A class extends one class, but implements as many interfaces as it wants.
One line replaces 40+ lines of constructor, getters, equals, and hashCode.
permits names every class allowed to extend it — finalized in Java 17.
instanceof used to require a redundant manual cast — not anymore.
@Override adds zero bytes to the running program — it exists purely for the compiler.
How Spring finds your @Autowired constructors without ever seeing your source.
Reading a whole file used to take a loop and a BufferedReader — now it's one line.
== on strings is a classic bug — identical content, different objects.
Before Java 9, 'public' meant visible from anywhere on the classpath, period.
Every official Java API page was generated from comments in the JDK's own source.
JUnit 6 (2025) is current — eight years after JUnit 5, now needing Java 17+.
Maven's build file is XML with no logic; Gradle's is an actual program.
G1 or ZGC — Java lets you pick a genuinely different collector for the job.
Code starts interpreted, then the JIT compiles the hot paths to native code live.
Makes 'might be absent' explicit in a signature — but null still exists everywhere else.
A real class — can have constructors, fields, and even per-constant method bodies.
java.time replaced the old Date class entirely, but Java never deletes anything.
A platform thread is expensive; a virtual thread is so cheap you can run millions.
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.
// 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 (int ↔ Integer, double ↔ Double) when needed — e.g. when storing in a List<Integer>. This is transparent but has a performance cost.
// 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 errorClasses and OOP
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).
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.
// 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 thrownThe 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.
// 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()); // trueConcurrency: 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.
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 heapModern Java: records, sealed classes, pattern matching
| Version | Feature | What it does |
|---|---|---|
| Java 8 (2014) | Lambdas, Streams, Optional | Functional-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 pattern | record Point(int x, int y) {} |
| Java 17 (2021) | Sealed classes, text blocks | Restrict which classes can extend a class |
| Java 21 (2023) | Virtual threads, pattern matching switch | Project Loom; exhaustive switch |
| Java 23 (2024) | Unnamed classes (preview), Markdown docs | No-boilerplate entry points |
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.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.
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.