Oracle Java SE 21 cheat sheet
Oracle Java SE 21 · Keep the key ideas within reach.
Handling Date, Time, Text, Numeric and Boolean Values
LocalDate, LocalTime, LocalDateTime and Instant are immutable; every plus/minus/with method returns a new instance instead of mutating the receiver.
Period measures date amounts (years, months, days) and pairs with LocalDate; Duration measures time amounts (hours, minutes, seconds, nanos) and pairs with Instant, LocalTime or LocalDateTime.
Instant is a point on the UTC timeline; ZonedDateTime adds a ZoneId with daylight-saving rules, while OffsetDateTime adds only a fixed ZoneOffset.
DateTimeFormatter patterns: yyyy year, MM month, dd day, HH 24-hour, hh 12-hour, mm minute, ss second, SSS millisecond; formatting a LocalDate with HH throws UnsupportedTemporalTypeException.
String is immutable; StringBuilder is mutable and unsynchronized; StringBuffer is mutable and synchronized. append returns the same builder, so calls chain.
A text block starts and ends with triple double-quotes; incidental leading whitespace is stripped relative to the least-indented content line and the position of the closing delimiter.
Autoboxing reuses cached Integer, Short, Byte, Long and Character objects in the range -128 to 127, so == between two boxed values can be false outside that range.
Math.round(float) returns int while Math.round(double) returns long; integer division truncates toward zero and division by zero on ints throws ArithmeticException.
Controlling Program Flow
switch with arrow labels (case X ->) has no fall-through; switch with colon labels falls through unless break, return or a thrown exception exits the block.
A switch expression must be exhaustive and produces a value; a block arm uses yield, and a plain break with a value is not permitted.
Java 21 pattern switch supports type patterns such as case Integer i, guarded patterns using when, and an explicit case null label.
A labeled break exits the labeled statement (outer: for(...) { ... break outer; }); a labeled continue jumps to the next iteration of the labeled loop.
while and for loops may execute zero times; do-while executes its body at least once because the condition is evaluated after the body.
The conditional operator requires both operands to be assignable to a common type; mixing a primitive with a boxed type triggers unboxing that can throw NullPointerException.
An enhanced for loop over an Iterable throws ConcurrentModificationException if the underlying collection is structurally modified during iteration; assigning new values to array elements is allowed.
== compares primitive values but compares reference identity for objects, so boxed values, Strings and collection elements must be compared with equals unless identity is intended.
Using Object-Oriented Concepts in Java
An overriding method must have the same name and parameter types, may widen access, may narrow the return type covariantly, and may not throw broader checked exceptions.
private, static and final methods are not overridden: private methods are hidden, static methods are hidden rather than polymorphic, and final methods cannot be redefined.
Interface fields are implicitly public static final; interface methods are implicitly public abstract unless declared default, static or private.
When two interfaces supply conflicting default methods, the implementing class must override the method and can delegate with InterfaceName.super.method().
A sealed type lists its permitted subtypes in a permits clause; each permitted subtype must be declared final, sealed, or non-sealed or compilation fails.
Records are implicitly final, extend java.lang.Record, and generate the canonical constructor, accessors, equals, hashCode and toString; compact constructors validate or normalize components.
this(...) or super(...) must be the first statement of a constructor; a class with no declared constructor receives a default no-arg constructor only when no other constructor exists.
A pattern variable declared by instanceof is in scope only where the compiler can prove the pattern matched, such as inside the if body or after an early return.
Enums implicitly extend java.lang.Enum, are final, cannot extend another class, can implement interfaces, and expose values(), valueOf(String) and name().
Exception Handling
Checked exceptions extend Exception but not RuntimeException: they must be caught or declared in a throws clause, whereas Error and RuntimeException subtypes are unchecked.
try-with-resources closes resources in reverse declaration order, closes them even when an exception propagates, and attaches close() failures as suppressed exceptions.
A multi-catch parameter catch (IOException | SQLException e) is implicitly final and its alternative types may not be related by subclassing.
finally runs whether or not an exception is thrown, except after System.exit or a JVM crash; a return or throw inside finally discards any pending exception.
An overriding method may not declare broader checked exceptions than the overridden method, but it may declare narrower ones or none at all.
Catch blocks must be ordered from most specific to most general; catching a supertype before its subtype is a compile-time error.
A custom checked exception extends Exception and an unchecked one extends RuntimeException; both typically pass a message up through super(message).
Closeable.close() declares IOException while AutoCloseable.close() declares Exception, so try-with-resources accepts both kinds of resource.
Arrays and Collections
Arrays expose a length field, List and other collections use size(), and String uses length(); using the wrong member does not compile.
List.of, Set.of and Map.of return immutable collections that reject null elements; mutator calls throw UnsupportedOperationException, though contained objects may still be mutable.
ArrayList gives O(1) index access; LinkedList gives O(1) insert and remove at ends. Both implement List, but only LinkedList also implements Deque.
HashSet and HashMap depend on equals and hashCode; TreeSet and TreeMap order by compareTo or a Comparator and treat compareTo == 0 as a duplicate key.
LinkedHashMap and LinkedHashSet preserve insertion order, or access order when the constructor is given accessOrder = true.
Queue methods add/remove/element throw on failure, while offer/poll/peek return false or null; ArrayDeque rejects null elements.
Comparator.comparing(keyExtractor).thenComparing(...).reversed() builds multi-level ordering, and List.sort plus Collections.sort accept a Comparator.
A wildcard List<? extends Number> can be read but not added to (except null); List<? super Integer> can be added to but reads only yield Object.
Removing elements through an Iterator is safe; adding or removing directly on the collection during iteration usually raises ConcurrentModificationException.
Streams and Lambda Expressions
A stream pipeline is a source, zero or more lazy intermediate operations, and exactly one terminal operation; a stream can be consumed only once and reuse throws IllegalStateException.
map transforms one element into one element; flatMap maps each element to a stream and flattens the results into a single stream.
Common functional interfaces in java.util.function: Function<T,R> apply, Predicate test, Supplier get, Consumer accept, BiFunction<T,U,R> apply.
Collectors.groupingBy returns Map<K, List>; partitioningBy returns a Map<Boolean, List> with exactly two keys; counting, summingInt, mapping and joining act as downstream collectors.
Collectors.toMap throws IllegalStateException on duplicate keys unless a merge function is supplied, and an optional fourth argument supplies the map factory.
Method reference forms: ClassName::staticMethod, instance::instanceMethod, ClassName::instanceMethod (first argument is the receiver), and ClassName::new for constructors.
Optional.ofNullable accepts null and yields an empty Optional; orElse always evaluates its argument, whereas orElseGet evaluates the supplier only when the Optional is empty.
No intermediate operation executes until a terminal operation is invoked; stateful operations such as sorted and distinct buffer the entire stream.
Parallel streams use ForkJoinPool.commonPool and relax ordering guarantees (findAny versus findFirst); they add overhead for small or I/O-bound workloads.
Packaging and Deploying Java Code
javac -d outputDir compiles classes into a directory tree mirroring the package name, so compiled output matches the package declaration.
jar --create --file app.jar --main-class com.example.Main -C classes . builds an executable jar whose manifest records Main-Class.
java -cp app.jar com.example.Main runs from a classpath; java -jar app.jar requires a Main-Class attribute in META-INF/MANIFEST.MF.
A modular jar contains module-info.class at its root; module-info.java uses requires, exports, opens, uses and provides ... with directives.
A jar placed on the module path without module-info.class becomes an automatic module named after the jar file unless the manifest sets Automatic-Module-Name.
Named modules cannot read the classpath or the unnamed module; the unnamed module reads all named modules plus the classpath.
jlink builds a custom runtime image from a set of modules, jpackage produces a platform-native installer, and jdeps analyses module dependencies.
Managing Concurrent Code Execution
Thread states are NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING and TERMINATED; a thread reaches TERMINATED after run() returns or throws.
Calling run() directly executes on the calling thread; only start() creates a new thread, and a second start() throws IllegalStateException.
synchronized methods and blocks acquire the object monitor; static synchronized acquires the Class object's monitor; wait/notify require holding that monitor or IllegalMonitorStateException is thrown.
volatile guarantees visibility and ordering for a single field but not atomicity; AtomicInteger and LongAdder provide atomic compound updates.
ExecutorService.execute takes a Runnable and returns void; submit accepts Runnable or Callable and returns a Future; shutdown() stops accepting new tasks.
Callable.call may return a value and throw checked exceptions, Runnable.run cannot; Future.get blocks and wraps task failures in ExecutionException.
CompletableFuture.thenApply behaves like map (Function), thenCompose like flatMap, thenAccept takes a Consumer, and supplyAsync starts an asynchronous stage.
Deadlock needs two or more threads each waiting on a lock the other holds; avoiding nested locks or acquiring them in a consistent global order prevents it.
Using Java I/O API
Byte streams (InputStream/OutputStream) move raw bytes; character streams (Reader/Writer) move text and apply charset encoding or decoding.
Files.readString, Files.writeString, Files.newBufferedReader and Files.newBufferedWriter are the concise java.nio.file helpers for text I/O.
Path.of and Paths.get create paths; resolve appends a relative path, relativize computes the difference between paths, and normalize removes . and .. segments.
Files.copy with StandardCopyOption.REPLACE_EXISTING overwrites, Files.move supports ATOMIC_MOVE, and Files.createDirectories creates any missing parents.
Files.walk, Files.list and Files.find return Stream backed by an open directory handle and should be closed with try-with-resources.
A class must implement java.io.Serializable to be serialized; transient and static fields are skipped, and serialVersionUID guards against incompatible class changes.
Wrapping order matters: new BufferedReader(new FileReader(path)) buffers characters, and new DataInputStream(new BufferedInputStream(...)) buffers bytes.
FileChannel works through ByteBuffer using flip() to switch from writing to reading and clear() or compact() to reset; RandomAccessFile supports positioned reads and writes.
Accessing Databases Using JDBC
DriverManager.getConnection(url, user, password) returns a Connection; the URL form is jdbc:subprotocol:subname, for example jdbc:postgresql://host/db.
PreparedStatement precompiles SQL with ? placeholders, binds values with setInt(1, v) or setString(2, s) using 1-based indexes, and prevents SQL injection from concatenated input.
Statement.executeQuery returns a ResultSet for SELECT, executeUpdate returns an int row count for INSERT/UPDATE/DELETE or 0 for DDL, and execute returns a boolean.
A ResultSet cursor starts before the first row; next() advances one row and returns false when rows are exhausted, and columns are read by 1-based index or by label.
Connections default to auto-commit true; setAutoCommit(false) with commit() and rollback() groups statements into a transaction, and Savepoint permits partial rollback.
CallableStatement created with prepareCall("{call proc(?, ?)}") invokes stored procedures; registerOutParameter declares OUT parameter types read with getX(index).
ResultSetMetaData supplies getColumnCount() and getColumnLabel(int); ResultSet.wasNull() distinguishes SQL NULL from a primitive zero value.
A DataSource is the preferred way to obtain pooled connections, and setNull(index, Types.INTEGER) writes SQL NULL into a parameter.