JVM, JDK/JRE, class loading, memory areas, data types, operators, static/final/volatile, initialization order, modern syntax and the classic gotchas.
Core language and runtime fundamentals that interviewers use to check whether a candidate understands what the JVM actually does. Baseline is Java 17/21 with Java 8 differences called out.
Theory
Q1
What is the difference between JDK, JRE and JVM?
basic
The JVM executes bytecode, the JRE = JVM + core libraries, and the JDK = JRE + developer tools (javac, jar, jlink, jshell).
Since Java 11 there is no separate JRE download; use the JDK, or build a trimmed runtime with jlink.
⚠ Follow-up traps
Is the JVM platform independent? No. Bytecode is portable; each OS needs its own JVM implementation.
Is Java purely interpreted? No. HotSpot interprets first, then JIT-compiles hot methods (C1/C2).
#jvm#jdk
Q2
Is Java pass-by-value or pass-by-reference?
basic
Always pass-by-value. For objects, the value copied is the reference, so a method can mutate the object but cannot make the caller's variable point elsewhere.
static void change(StringBuilder sb, String s) { sb.append("!"); // visible to caller sb = new StringBuilder("new"); // not visible s = s + "?"; // not visible, Strings are immutable}
⚠ Follow-up traps
What does the caller see after change(sb, s) with sb="a", s="b"?sb is "a!", s is "b".
#methods#references
Q3
What are the main components of the JVM architecture?
basic
Class loader subsystem, runtime data areas, execution engine, and native interface.
Class loader subsystem: loads, links and initializes classes.
Runtime data areas: heap, per-thread stacks, program counter registers, native method stacks, metaspace (method area).
Which areas are shared between threads? Heap and metaspace. Stacks and PC registers are per-thread.
Is the JVM specification the same as HotSpot? No. The spec defines behaviour; HotSpot, OpenJ9 and GraalVM are implementations.
#jvm#architecture
Q4
What are the phases of class loading?
intermediate
Loading, linking (verification, preparation, resolution) and initialization.
Loading: read the .class bytes and create a Class object.
Verification: check bytecode structure and type safety.
Preparation: allocate static fields and set them to default values (0, null, false).
Resolution: replace symbolic references with direct ones (may be lazy).
Initialization: run static initializers and assign static field initializer values, in textual order.
⚠ Follow-up traps
What value does a static field have during preparation? The type default, not the declared initializer; the initializer runs in the initialization phase.
When is a class initialized? On first new, static method call, non-constant static field access, or Class.forName with initialization. Compile-time constants (static final int X = 5) do not trigger it.
#class-loading#jvm
Q5
Explain the class loader hierarchy and the delegation model.
intermediate
Loaders delegate to their parent first; a child loads a class only if every ancestor failed. This prevents user code from replacing core classes like java.lang.String.
Bootstrap loader: core java.base classes, written in native code (getClassLoader() returns null).
Platform loader (extension loader before Java 9): other JDK modules.
Who breaks parent-first delegation? Servlet containers (webapp loaders look locally first), OSGi, and some plugin frameworks.
Can two loaders load the same class name? Yes, and the results are different runtime types; casting between them throws ClassCastException.
#class-loading#classloader
Q6
What are the JVM runtime memory areas?
basic
Heap (objects), thread stacks (frames with locals and operand stack), metaspace (class metadata), PC registers, native stacks, plus off-heap memory such as direct buffers and the code cache.
Heap and metaspace are shared; stacks are per-thread.
Total process memory = heap + metaspace + thread stacks + code cache + direct memory + GC overhead.
⚠ Follow-up traps
Does -Xmx cap the whole process? No, only the heap. Native memory is additional.
Where do local variables live? Primitives and references live in the stack frame; the objects they reference live on the heap.
#memory#jvm
Q7
How is the heap organized in generational collectors?
intermediate
Young generation (Eden + two survivor spaces) and old generation. New objects go to Eden; survivors of minor GCs are copied between survivor spaces and promoted to old after reaching a tenuring threshold.
Based on the weak generational hypothesis: most objects die young.
G1 uses equal-sized regions that play the eden/survivor/old roles dynamically.
⚠ Follow-up traps
Where do huge objects go? Large arrays can be allocated directly in old gen (G1: humongous regions).
Is there still a permanent generation? No, removed in Java 8.
#heap#gc
Q8
What does the thread stack contain, and what is a stack frame?
basic
Each method call pushes a frame holding local variables, an operand stack and a reference to the constant pool. The frame is popped on return or exception unwinding.
Size is set with -Xss (default typically 1 MB on 64-bit Linux).
Too-deep recursion causes StackOverflowError.
⚠ Follow-up traps
Does a larger -Xss always help? It only delays overflow and multiplies memory cost by thread count.
Are objects ever allocated on the stack? Not by language semantics; escape analysis may scalar-replace them, which is an optimization.
#stack#memory
Q9
What is Metaspace and how does it differ from PermGen?
intermediate
Metaspace stores class metadata in native memory and replaced PermGen in Java 8. It grows dynamically instead of having a fixed size inside the Java heap.
Limit it with -XX:MaxMetaspaceSize; unlimited by default.
Metadata is freed when the defining class loader becomes unreachable.
Interned strings and static field values moved to the heap (Java 7/8).
⚠ Follow-up traps
What causes OutOfMemoryError: Metaspace? Class loader leaks, excessive dynamic class generation (proxies, bytecode libraries), or a too-low max.
Is Metaspace part of the heap? No, it is native memory.
#metaspace#memory
Q10
List the primitive types, their sizes and default values.
basic
byte 8-bit, short 16, int 32, long 64, float 32, double 64, char 16 (unsigned), boolean (JVM-dependent size, one bit of information).
Fields default to 0, 0.0, '\u0000', false; references default to null.
Local variables have no default and must be definitely assigned before use.
⚠ Follow-up traps
Is char signed? No, it is the only unsigned integral type, range 0..65535.
Does int size vary by platform? No, sizes are fixed by the language spec.
#data-types#primitives
Q11
How do autoboxing and unboxing work?
basic
The compiler inserts Integer.valueOf(int) for boxing and intValue() for unboxing. No magic at runtime, just generated calls.
Integer, Long, Short, Byte, Character (0..127) cache small values; Boolean has two constants.
Float and Double have no cache.
⚠ Follow-up traps
What if the wrapper is null when unboxed?NullPointerException.
Why is boxing in tight loops slow? Each boxed value may allocate an object and adds GC pressure; prefer primitive streams or arrays.
#autoboxing#wrapper-classes
Q12
What is the difference between widening and narrowing conversions?
basic
Widening (int to long) is implicit and safe in range; narrowing (long to int) needs an explicit cast and can lose data via truncation of high bits.
int to float and long to double are widening but can lose precision.
Compound assignment (+=) includes an implicit narrowing cast.
⚠ Follow-up traps
Does byte b = 10; compile without a cast? Yes, constant expressions that fit the target type are allowed.
What is (byte) 200?-56, the low 8 bits reinterpreted as signed.
#casting#data-types
Q13
Why should you not use `float`/`double` for money?
basic
Binary floating point cannot represent most decimal fractions exactly (0.1), so errors accumulate. Use BigDecimal (constructed from a String) or integer minor units.
IEEE 754: 1 sign bit, exponent, mantissa.
BigDecimal needs an explicit RoundingMode for non-terminating divisions.
⚠ Follow-up traps
What does new BigDecimal(0.1) hold? The exact binary value of the double, 0.1000000000000000055...; use BigDecimal.valueOf(0.1) or a string.
Does BigDecimal.equals ignore scale? No. 2.0 and 2.00 are not equal; use compareTo.
#floating-point#bigdecimal
Q14
How does `char` relate to Unicode and integer arithmetic?
intermediate
char is a 16-bit UTF-16 code unit, and arithmetic on it promotes to int. Characters outside the BMP take two chars (a surrogate pair).
Use String.codePoints() or codePointAt for real characters.
'a' + 1 is the int 98; (char) ('a' + 1) is 'b'.
⚠ Follow-up traps
What does "😀".length() return?2, since it is two UTF-16 units.
Does c++ on a char compile? Yes, compound/increment operators include the narrowing cast.
#char#unicode
Q15
Why are Strings immutable and what is the string pool?
basic
String is final with a private final value array, which makes it thread-safe, cacheable by hash and safe as a map key. Literals are interned into a pool on the heap so identical literals share one instance.
Immutability enables the pool, hash caching and security (class names, paths).
Since Java 9 strings use compact Latin-1/UTF-16 byte arrays.
⚠ Follow-up traps
Is the string pool in PermGen? It was before Java 7; since Java 7 it is on the heap.
Does new String("a") create one object? It creates a new heap object; the literal "a" is in the pool separately.
#string#string-pool
Q16
Compare `String`, `StringBuilder` and `StringBuffer`.
basic
String is immutable; StringBuilder is a mutable, unsynchronized builder; StringBuffer is the synchronized legacy version.
Use StringBuilder for loops that append; + in a loop creates a builder per iteration.
Java 9+ compiles + using invokedynamic (StringConcatFactory).
⚠ Follow-up traps
Is StringBuffer useful for thread-safe building? Rarely; each call is synchronized but compound operations are not atomic.
Is + always slower than StringBuilder? No, a single expression is optimized equally; only loops hurt.
#string#stringbuilder
Q17
What is the difference between `==` and `equals`?
basic
== compares primitives by value and references by identity; equals compares logical content if overridden. The default Object.equals is identity.
⚠ Follow-up traps
Why compare strings with equals? Strings built at runtime are different objects even with equal content.
Is == between Integer and int identity? No, the Integer is unboxed and values compared.
#equality#object
Q18
What is short-circuit evaluation?
basic
&& and || skip evaluating the right operand when the left already decides the result. & and | on booleans always evaluate both sides.
if (s != null && s.length() > 3) { /* safe */ }
⚠ Follow-up traps
What does s != null & s.length() > 3 do for null s? Throws NullPointerException, since both operands evaluate.
Does ?: evaluate both branches? No, only the chosen one.
#operators#logical
Q19
How do pre- and post-increment differ?
basic
++i increments then yields the new value; i++ yields the old value then increments. As standalone statements they are equivalent.
⚠ Follow-up traps
Is i++ atomic? No, it is read-modify-write; even for volatile fields.
What does i = i++ leave in i? The original value, because the old value is assigned back after the increment.
#operators#increment
Q20
What happens on integer overflow in Java?
intermediate
It wraps silently in two's complement; no exception. Integer.MAX_VALUE + 1 equals Integer.MIN_VALUE.
Use Math.addExact, multiplyExact, toIntExact to throw ArithmeticException.
Floating point overflows to Infinity instead.
⚠ Follow-up traps
What is Math.abs(Integer.MIN_VALUE)?Integer.MIN_VALUE (still negative), since +2^31 does not fit.
What about integer division by zero?ArithmeticException; for doubles it gives Infinity or NaN.
#overflow#arithmetic
Q21
Explain `<<`, `>>` and `>>>`.
intermediate
<< shifts left filling zeros, >> is an arithmetic shift that preserves the sign bit, and >>> is a logical shift that fills with zeros.
The shift distance is masked: int uses the low 5 bits, long the low 6 bits.
x >> 1 equals floor division by 2; -7 >> 1 is -4, while -7 / 2 is -3.
⚠ Follow-up traps
What is 1 << 32 for an int?1, because the distance is 32 & 31 = 0.
What is -1 >>> 1 for an int?2147483647.
#bitwise#operators
Q22
How does the ternary operator determine its result type?
advanced
If both operands are numeric, binary numeric promotion applies; if one is a boxed type and the other a primitive, the result is unboxed. So true ? 1 : 2.0 yields 1.0.
Mixed Integer/int with a null operand can cause an unboxing NPE.
With two references the result is the lub (least upper bound) type.
⚠ Follow-up traps
What does Object o = true ? 1 : "x"; give? An Integer 1; there is no numeric promotion with a String.
What does flag ? (Integer) null : 0 do? NPE: the 0 makes it an int expression, so the null unboxes.
#operators#ternary#promotion
Q23
How does the classic `switch` statement behave, including fall-through?
basic
Execution jumps to the matching case and continues through subsequent cases until a break or the end. default can appear anywhere.
Supported selector types: byte, short, char, int, their wrappers, enum, String (Java 7), and patterns (Java 21).
⚠ Follow-up traps
Can a case label be a variable? Only a compile-time constant (final with constant initializer).
What if the selector is a null String? NPE in a classic switch.
#switch#control-flow
Q24
What are switch expressions and what do they improve?
intermediate
Since Java 14 switch can be an expression that produces a value, uses -> arms without fall-through, and must be exhaustive.
int days = switch (month) { case FEB -> 28; case APR, JUN, SEP, NOV -> 30; default -> { int d = 31; yield d; }};
Over an enum or sealed type exhaustiveness is checked without default.
Java 21 adds pattern matching and case null.
⚠ Follow-up traps
Can you mix -> and : labels? No, a single switch uses one form.
What happens to a missing enum constant at runtime? For switches without default over enums the compiler inserts a MatchException (Java 21) / IncompatibleClassChangeError path.
#switch#java14
Q25
How does the enhanced for loop work, and what are its limits?
basic
For arrays it compiles to an index loop; for Iterable it uses iterator(). You cannot see the index or remove elements safely.
⚠ Follow-up traps
Why ConcurrentModificationException when removing in for-each? The list's modCount changes and the iterator detects it; use Iterator.remove() or removeIf.
Does reassigning the loop variable change the collection? No, it is a local copy of the element reference.
#loops#iterator
Q26
How do labeled `break` and `continue` work?
intermediate
A label names an enclosing statement; break label exits it and continue label jumps to the next iteration of that labeled loop. It is structured, not a goto.
outer:for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { if (j == 1) continue outer; if (i == 2) break outer; }
⚠ Follow-up traps
Can you label any statement? Yes, including blocks, but continue targets only loops.
Is goto usable? It is a reserved but unused keyword.
#control-flow#labels
Q27
What does the `static` keyword mean for fields, methods, blocks and nested classes?
basic
static members belong to the class, not to instances; they exist once per class loader and are initialized when the class is initialized.
Static methods cannot access instance members directly and have no this.
A static nested class has no implicit reference to an outer instance, unlike an inner class.
⚠ Follow-up traps
Can static methods be overridden? No, they are hidden; resolution uses the declared type.
Is a static field unique per JVM? Per class loader, not per JVM.
#static#oop
Q28
What are static and instance initializer blocks, and when do they run?
intermediate
A static {} block runs once during class initialization; an instance {} block runs on every construction, before the constructor body (after super()).
Both run in textual order together with field initializers.
Instance initializers are rarely useful; constructors or field initializers are clearer.
⚠ Follow-up traps
Can a static initializer throw a checked exception? No, it must not complete abruptly with one; unchecked ones become ExceptionInInitializerError.
Can an instance initializer run without a constructor call? No; the compiler copies it into every constructor that calls super.
#initialization#static
Q29
What does `final` mean on variables, methods and classes?
basic
A final variable can be assigned once, a final method cannot be overridden, and a final class cannot be extended.
A blank final field must be assigned in every constructor or initializer.
Final fields get special safe-publication guarantees in the Java Memory Model.
⚠ Follow-up traps
Is a final parameter allowed? Yes, it just prevents reassignment inside the method.
Does final make a method faster? Not meaningfully; the JIT devirtualizes by class hierarchy analysis anyway.
#final#oop
Q30
Does `final` make an object immutable?
basic
No. final fixes the reference, not the object's state; final List<String> l can still have elements added.
True immutability: final class, private final fields, no setters, defensive copies in and out.
List.of, Map.of and records (shallowly) support this style.
⚠ Follow-up traps
Does Collections.unmodifiableList copy? No, it is a read-only view; changes to the backing list show through.
Is String deeply immutable? Its state cannot change, but reflection and Unsafe can bypass that; the language contract holds.
#final#immutability
Q31
What does the `transient` keyword do?
basic
transient excludes a field from default Java serialization; on deserialization it gets the type default (null, 0, false).
Used for derived data, caches, and secrets such as passwords.
Does not apply to static fields, which are never serialized anyway.
JSON libraries such as Jackson ignore transient unless configured; JPA treats it as non-persistent.
⚠ Follow-up traps
Are field initializers rerun on deserialization? No, constructors of Serializable classes are not called; restore state in readObject or readResolve.
Does the first non-serializable superclass get its constructor called? Yes, its no-arg constructor.
#transient#serialization
Q32
What does `volatile` guarantee?
intermediate
Visibility and ordering: a write to a volatile variable happens-before every subsequent read of it, and reads/writes are not reordered across it. It does not provide atomicity for compound actions.
Good for flags and safe publication of immutable objects.
long and double volatile reads/writes are atomic (non-volatile may tear on 32-bit JVMs per spec).
⚠ Follow-up traps
Is volatile int count; count++ thread-safe? No, use AtomicInteger or a lock.
Does volatile on an array make elements volatile? No, only the reference.
#volatile#jmm
Q33
What does "effectively final" mean and why do lambdas need it?
intermediate
A local variable is effectively final if it is never reassigned after initialization. Lambdas and inner classes capture the value, so captured locals must not change.
⚠ Follow-up traps
How do you mutate a captured counter? Use a field, an AtomicInteger, or a one-element array; the reference stays effectively final.
Do captured fields have the same limit? No, lambdas capture this and can mutate fields freely.
#lambda#final
Q34
What is the object initialization order?
intermediate
Class init: superclass static initializers, then subclass static, once. For each instance: superclass instance initializers and constructor body, then subclass instance initializers and constructor body.
Within one class, static fields/blocks and instance fields/blocks run in textual order.
Fields not yet initialized hold defaults, which is why calling an overridable method from a constructor is dangerous.
⚠ Follow-up traps
What does a subclass method see in a field when called from the super constructor? The default value (0/null), as the subclass field initializers have not run.
Are static blocks rerun for every new? No, only on first class initialization.
#initialization#constructors
Q35
How do constructors, `this(...)` and `super(...)` chain?
basic
Every constructor starts with this(...) or super(...), explicit or implicit (super()). The call must be the first statement (Java 22 preview relaxes this for code that does not reference this).
If a class declares any constructor, the compiler does not add the default one.
If the superclass lacks a no-arg constructor, the subclass must call another explicitly.
⚠ Follow-up traps
Can a constructor call both this() and super()? No, only one; this() delegates and eventually reaches super.
Can constructors be inherited or final? Neither; constructors are not members.
#constructors#oop
Q36
How does `var` (local variable type inference) work?
basic
var lets the compiler infer the type of a local variable from its initializer (Java 10). The type is still static and fixed; var is not dynamic typing.
Not allowed: fields, method parameters/returns, no initializer, null initializer, array initializer {1,2}.
var is a reserved type name, not a keyword; var var = 1; compiles.
⚠ Follow-up traps
What is the type of var list = new ArrayList<>();?ArrayList<Object>.
Does var hurt readability? It can when the initializer does not reveal the type; use it when the right side is obvious.
#var#java10
Q37
What are records and what does the compiler generate?
intermediate
A record is a transparent, shallowly immutable data carrier (Java 16). The compiler generates private final fields, a canonical constructor, accessors (name(), not getName()), equals, hashCode and toString.
record Point(int x, int y) { Point { // compact constructor if (x < 0) throw new IllegalArgumentException(); }}
Records are implicitly final, cannot extend classes, but can implement interfaces and have static members.
No instance fields beyond the components.
⚠ Follow-up traps
Is a record deeply immutable? No, a List component can still be mutated; copy defensively in the compact constructor.
Can records be JPA entities? No (final, no no-arg constructor); they work well for DTOs and projections.
#records#java16
Q38
What are text blocks?
basic
Multi-line string literals delimited by """ (Java 15). Incidental indentation is stripped based on the least-indented line (including the closing delimiter), and trailing spaces are removed.
String json = """ {"name": "A"} """;
Line endings are normalized to \n.
\ at line end suppresses the newline; \s keeps a trailing space.
⚠ Follow-up traps
Does the closing """ position matter? Yes: placing it on its own line adds a trailing newline and affects indentation stripping.
Is a text block a different type? No, it is a regular String (and is interned like any literal).
#text-blocks#java15
Q39
How does an object become eligible for garbage collection?
basic
When it is no longer reachable from any GC root (thread stacks, static fields, JNI references, active class loaders). The GC traces reachability; it does not count references.
Cyclic references among unreachable objects are collected.
System.gc() is only a hint.
⚠ Follow-up traps
Does setting a local variable to null help? Rarely; the JIT already treats a variable as dead after its last use.
Can an eligible object be resurrected? Via finalize in old code; finalization is deprecated for removal (Java 18).
#gc#reachability
Q40
What are the common garbage collectors and their defaults?
intermediate
Serial (single thread), Parallel (throughput), G1 (balanced, default since Java 9 on server-class machines), ZGC and Shenandoah (low pause, concurrent compaction).
Select with -XX:+UseSerialGC, -XX:+UseParallelGC, -XX:+UseG1GC, -XX:+UseZGC.
Generational ZGC arrived in Java 21 (-XX:+ZGenerational, default in 23).
Java 8 default is Parallel GC.
⚠ Follow-up traps
Which collector for tiny containers? Serial; the JVM picks it when fewer than 2 CPUs or under ~1792 MB are available.
Is lower pause always better? No, concurrent collectors cost throughput and CPU.
#gc#g1#zgc
Q41
What is a stop-the-world pause and what are GC roots?
intermediate
A stop-the-world pause halts all application threads at a safepoint so the GC can work with a consistent heap. GC roots are the starting points for tracing: local variables on thread stacks, static fields, JNI handles, and live class loaders.
Concurrent collectors shrink pauses but still need short pauses for root scanning.
Time-to-safepoint can be long when a thread is in a counted loop.
⚠ Follow-up traps
Does a minor GC stop the world? Yes, in all generational collectors young collections pause the application.
Are pauses proportional to heap size? For ZGC and Shenandoah no; for Parallel GC full collections yes.
#gc#safepoint
Q42
What are strong, soft, weak and phantom references?
advanced
Strong references block collection. Soft references are cleared under memory pressure (caches), weak ones at the next GC when only weakly reachable (WeakHashMap), phantom ones are enqueued after finalization and used for cleanup via Cleaner.
⚠ Follow-up traps
Is WeakHashMap safe if the value references the key? No, the key stays strongly reachable via the value and the entry never clears.
Why prefer Cleaner over finalize? Finalizers are unpredictable, slow and deprecated for removal.
#references#gc
Q43
How does the JIT compiler work in HotSpot?
intermediate
The JVM starts by interpreting bytecode, profiles invocation and loop counts, and compiles hot methods to native code. Tiered compilation uses C1 (fast, light optimization) first and C2 (aggressive, profile-guided) for the hottest code.
Compiled code lives in the code cache.
Deoptimization falls back to the interpreter when an assumption (e.g., a monomorphic call site) breaks.
-XX:+PrintCompilation shows compile events.
⚠ Follow-up traps
Why is the first run of a benchmark slower? Warm-up: code is still interpreted or C1-compiled.
Can the JIT make code faster than C++? In some cases, thanks to runtime profile-based speculation.
#jit#performance
Q44
Which optimizations does the JIT perform?
advanced
Method inlining, escape analysis (scalar replacement, lock elision), loop unrolling, dead code elimination, range-check elimination and devirtualization.
Inlining is limited by bytecode size (MaxInlineSize, FreqInlineSize).
Escape analysis can avoid heap allocation for objects that do not leave a method.
⚠ Follow-up traps
Does escape analysis put objects on the stack? Not literally; it replaces the object by its fields in registers.
Does dead-code elimination break naive microbenchmarks? Yes; unused results get removed, so use JMH Blackhole.
#jit#escape-analysis
Q45
What are the key JVM memory flags?
basic
-Xms initial heap, -Xmx max heap, -Xss thread stack size, -XX:MaxMetaspaceSize metaspace cap, -XX:MaxDirectMemorySize direct buffers.
Setting -Xms equal to -Xmx avoids resize pauses.
In containers use -XX:MaxRAMPercentage (default 25%).
⚠ Follow-up traps
Why does the process use more RSS than -Xmx? Metaspace, stacks, code cache, direct buffers and GC structures.
Is the JVM container aware? Yes since Java 10 (backported to 8u191).
#jvm-flags#memory
Q46
How does method overloading resolution work versus overriding?
intermediate
Overloads are chosen at compile time using the static argument types; overrides are dispatched at runtime using the object's actual class.
Overload phases: exact/widening, then boxing, then varargs.
Overriding requires the same signature, a compatible return type (covariant) and no weaker access.
⚠ Follow-up traps
Are fields polymorphic? No, field access uses the declared type.
Can an override throw broader checked exceptions? No, only the same, narrower or unchecked ones.
#overloading#overriding#polymorphism
Q47
What are the access modifiers in Java?
basic
private (class), package-private (default, same package), protected (package plus subclasses), public (everywhere). With modules (Java 9) a package must also be exportsed.
⚠ Follow-up traps
Can a subclass in another package access a protected member via a parent-typed reference? No, only via its own type or subtype.
Can top-level classes be private? No, only public or package-private.
#access-modifiers#oop
Q48
How do varargs work?
basic
void f(String... a) is compiled to String[] a; the compiler packs the arguments into an array. It must be the last parameter, and only one is allowed.
⚠ Follow-up traps
What does f() pass? An empty array, not null.
Which overload wins between f(int) and f(int...)? The fixed-arity one; varargs is the last phase.
#varargs#methods
Q49
What do interface default, static and private methods add?
intermediate
Default methods (Java 8) let interfaces evolve without breaking implementors; static methods hold utilities; private methods (Java 9) share code between defaults. Interfaces still cannot hold instance state.
If two interfaces supply the same default, the class must override and may pick one via A.super.m().
A class method always wins over an interface default.
⚠ Follow-up traps
Is an interface with defaults an abstract class? No: no constructors, no instance fields, multiple inheritance of behaviour only.
Can a default method override Object.equals? No, it is a compile error.
#interfaces#java8
Q50
What is the `equals`/`hashCode` contract?
intermediate
Equal objects must have equal hash codes; equals must be reflexive, symmetric, transitive, consistent and false for null. Unequal objects may share a hash code.
Override both together; hash collections break otherwise.
Do not use mutable fields in hashCode for objects stored in hash sets/maps.
⚠ Follow-up traps
What if only equals is overridden?HashMap lookups likely miss, because the identity hashes differ.
What does Objects.hash(a, b) cost? It allocates a varargs array; hand-write for hot paths.
#equals#hashcode
Q51
What are pattern matching for `instanceof` and sealed types?
intermediate
if (o instanceof String s) tests and binds in one step (Java 16). sealed classes/interfaces (Java 17) restrict permitted subtypes, which enables exhaustive switch without default.
sealed interface Shape permits Circle, Square {}record Circle(double r) implements Shape {}record Square(double a) implements Shape {}double area(Shape s) { return switch (s) { case Circle c -> Math.PI * c.r() * c.r(); case Square q -> q.a() * q.a(); };}
(The switch pattern form is final in Java 21.)
⚠ Follow-up traps
What is the scope of the binding s? Only where the match is definitely true, e.g. if (!(o instanceof String s)) return; makes s available after.
Does null instanceof String s match? No, instanceof is false for null.
#pattern-matching#sealed#java17
Q52
What are the methods of `java.lang.Object` and which ones are commonly overridden?
basic
equals, hashCode, toString, getClass, clone, finalize (deprecated), wait, notify, notifyAll. Typically equals, hashCode and toString are overridden.
getClass, wait, notify and notifyAll are final.
wait/notify require holding the object's monitor.
⚠ Follow-up traps
Why is clone considered flawed? It is protected, shallow, needs Cloneable (a marker without the method) and bypasses constructors; prefer copy constructors.
What does default toString print?ClassName@hexHashCode.
#object#methods
Scenarios
Q53
What does this print: `Integer a = 127, b = 127, c = 128, d = 128; System.out.println((a == b) + " " + (c == d));`?
intermediate
true false. Autoboxing uses Integer.valueOf, which caches values from -128 to 127, so a and b are the same object while c and d are different objects. Always compare boxed values with equals.
⚠ Follow-up traps
Can the cache range change? Yes, the upper bound via -XX:AutoBoxCacheMax=<n>.
What about new Integer(127) == new Integer(127)?false; the constructor is deprecated for removal.
#integer-cache#equality
Q54
What does the string pool comparison with `==`, `new String` and `intern()` print?
basic
Trace the code below.
String a = "hi";String b = "hi";String c = new String("hi");System.out.println((a == b) + " " + (a == c) + " " + (a == c.intern()) + " " + a.equals(c));
true false true true. Both literals share one pooled instance, new String creates a distinct object, intern() returns the pooled instance, and equals compares content.
⚠ Follow-up traps
How many String objects does new String("hi") create at most? Two if "hi" was not yet in the pool (the literal and the copy), otherwise one.
Why not rely on == for strings? It only works by accident of interning.
#string-pool#equality
Q55
Which of these comparisons is true?
advanced
Trace the code below.
final String f = "a";String n = "a";System.out.println(((f + "b") == "ab") + " " + ((n + "b") == "ab"));
true false. f is a constant variable, so f + "b" is a compile-time constant folded to the pooled "ab". n is not final, so the concatenation runs at runtime and creates a new object.
⚠ Follow-up traps
What if final String f = getValue();? Not a constant variable; the result is false.
Does n.concat("b").intern() == "ab"?true.
#string-pool#constant-folding
Q56
A service parses millions of CSV rows with many repeated values and is running out of heap. Would `String.intern()` help?
advanced
It can reduce duplicates but is usually the wrong tool. The JVM string table is a fixed-bucket native hash table; heavy interning adds contention and GC cost. Prefer a bounded application-level dedup map, or on G1 enable -XX:+UseStringDeduplication, which shares the backing arrays of duplicate strings in the background.
Measure first with a heap histogram or a heap dump (duplicate strings view in MAT).
Better still: parse into enums, ints or dictionary IDs.
⚠ Follow-up traps
Does string deduplication merge String objects? No, only their internal byte[]; identity stays distinct.
Is interned data ever collected? Yes, since Java 7 pooled strings live on the heap and are collectable.
#string-pool#memory#g1
Q57
What does `i = i++` leave in `i`?
basic
Trace the code below.
int i = 5;i = i++;System.out.println(i);
5. i++ yields the old value 5 and increments i to 6, then the assignment overwrites i with the old value 5.
⚠ Follow-up traps
And int a = 1; a = a++ + ++a;?4: 1 + 3, with a ending as 4.
Does i = ++i differ? Yes, it results in 6.
#operators#increment
Q58
Does `short s = 1; s += 1;` compile? What about `s = s + 1;`?
intermediate
s += 1 compiles; s = s + 1 does not. s + 1 is an int and assigning to short needs a cast, while a compound assignment is defined as s = (short) (s + 1).
short s = 1;s += 1; // ok, s == 2// s = s + 1; // error: incompatible types: possible lossy conversion from int to shorts = (short) (s + 1);
⚠ Follow-up traps
Does s += 1.9 compile? Yes, with narrowing; s becomes 2 (the double sum 2.9 truncated).
What if s is final short s = 1; short t = s + 1;? Compiles; s + 1 is a constant expression that fits.
#compound-assignment#casting
Q59
What does `System.out.println(0.1 + 0.2 == 0.3);` print and how should you compare doubles?
basic
false; the sum is 0.30000000000000004. Compare with a tolerance (Math.abs(a - b) < 1e-9) or use BigDecimal for exact decimals.
⚠ Follow-up traps
Does 0.1 + 0.2 == 0.3 hold in BigDecimal?new BigDecimal("0.1").add(new BigDecimal("0.2")).compareTo(new BigDecimal("0.3")) == 0 is true.
Is Double.compare the right fix? No, it is an exact comparison with total ordering.
#floating-point#equality
Q60
What do these lines print?
basic
Trace the code below.
System.out.println(Integer.MAX_VALUE + 1);long l = 1_000_000 * 1_000_000;System.out.println(l);System.out.println(Integer.MAX_VALUE + 1L);
-2147483648, -727379968, 2147483648. The multiplication of two int literals is done in 32-bit before widening to long, so it already overflowed; make one operand long (1_000_000L).
⚠ Follow-up traps
How do you make overflow fail fast?Math.multiplyExact throws ArithmeticException.
Is l correct if declared long l = 1_000_000L * 1_000_000? Yes, 1000000000000.
#overflow#arithmetic
Q61
What do `char` arithmetic and concatenation print here?
basic
Trace the code below.
char c = 'a';System.out.println(c + 1);System.out.println((char) (c + 1));System.out.println("" + c + 1);System.out.println('a' + 'b');
98, b, a1, 195. Arithmetic promotes char to int; string concatenation uses the character itself.
⚠ Follow-up traps
What does char c = 'a'; c += 1; do? Compiles and yields 'b'.
Does char x = 65; compile? Yes, constant that fits; x is 'A'.
#char#promotion
Q62
What does this print: `System.out.println(true ? 1 : 2.0);`?
intermediate
1.0. Binary numeric promotion makes the conditional's type double, so the chosen 1 is widened.
⚠ Follow-up traps
What about System.out.println(true ? 1 : 'a');? With a constant int that fits in char, the type is char, printing the char with code 1 (a control character).
What about true ? (Object) 1 : 2.0? Prints 1; the cast stops numeric promotion.
#ternary#promotion
Q63
Why does this throw a `NullPointerException`?
intermediate
Trace the code below.
Integer x = null;boolean flag = false;int y = flag ? 1 : x;
The operands are int and Integer, so the expression type is int and x is unboxed when the false branch is selected; x.intValue() on null throws. Fix by keeping the type boxed (flag ? Integer.valueOf(1) : x) or testing null explicitly.
⚠ Follow-up traps
Would flag ? 1 : null throw? No; the type is Integer and null is just assigned to an Integer. Assigning that to int would throw.
Does Integer z = flag ? 1 : x; throw? Yes, same typing rule.
#ternary#unboxing#npe
Q64
What is the output order with static blocks, instance blocks and constructors?
P-static, C-static, P-init, P-ctor, C-init, C-ctor, P-init, P-ctor, C-init, C-ctor. Static blocks run once, superclass first; each instance runs super initializers and constructor before the subclass ones.
⚠ Follow-up traps
Does Child.class literal trigger C-static? No, a class literal does not initialize the class.
What if main is in Child?P-static and C-static print before main starts.
#initialization-order#static
Q65
What does `new B()` print, and why is it a bug risk?
advanced
Trace the code below.
class A { A() { show(); } void show() { }}class B extends A { int x = 5; void show() { System.out.println(x); }}
0. A's constructor runs before B's field initializers, and the overridden show is dispatched virtually, so it sees the default value. Never call overridable methods from constructors.
⚠ Follow-up traps
What if the field is final int x = 5;? It prints 5; a final field with a constant initializer is a constant variable inlined by the compiler.
What if it is final int x; B() { x = 5; }? Still 0 at that point.
2. A return in finally overrides the earlier return and also discards any pending exception; compilers warn about it.
⚠ Follow-up traps
What does int x = 1; try { return x; } finally { x = 2; } return?1; the return value is saved before finally runs.
If try returns a mutable object and finally mutates it? The caller sees the mutation, since the reference is the same.
#finally#exceptions
Q67
Does a `finally` block always run?
intermediate
Nearly always. It runs after normal completion, return, break or an exception. It does not run if the JVM exits (System.exit, Runtime.halt, crash, kill -9), or the thread is killed or hangs forever in try.
If both try and finally throw? The finally exception wins and the first is lost (try-with-resources keeps it as suppressed).
Do daemon threads run their finally on JVM shutdown? Not guaranteed; they are abandoned.
#finally#exceptions
Q68
What does a classic switch with fall-through print for n = 2?
basic
Trace the code below.
int n = 2;switch (n) { case 1: System.out.print("one "); case 2: System.out.print("two "); case 3: System.out.print("three "); break; default: System.out.print("other ");}
two three . Execution starts at case 2 and falls through into case 3 until break.
⚠ Follow-up traps
What if break is removed from case 3? It also falls into default and prints two three other .
How does the arrow form change this?case 2 -> never falls through.
#switch#fall-through
Q69
What is wrong with this code?
intermediate
Trace the code below.
String r = switch (day) { case 1, 7 -> "weekend"; case 2, 3, 4, 5, 6 -> "weekday";};
Compile error: the switch expression does not cover all possible input values. For int a default is mandatory; only enums and sealed types can be exhaustive without it.
⚠ Follow-up traps
What if day is an enum covering all constants? It compiles without default.
How do you return early from inside an arm block? You cannot return; use yield to produce the value.
#switch-expression#exhaustiveness
Q70
What happens with `switch` on a null `String`?
intermediate
Trace the code below.
String s = null;switch (s) { case "a": break; default: break; }
NullPointerException, since the classic switch calls hashCode/equals on the selector. Java 21 pattern switches allow case null -> ... to handle it explicitly.
String r = switch (s) { case null -> "none"; case "a" -> "A"; default -> "other";};
⚠ Follow-up traps
Does a pattern switch without case null still throw? Yes, an NPE.
Can case null, default -> be combined? Yes, in Java 21.
#switch#npe#java21
Q71
What happens when you remove elements inside a for-each loop?
intermediate
Trace the code below.
List<Integer> l = new ArrayList<>(List.of(1, 2, 3));for (Integer i : l) if (i == 1) l.remove(i);
ConcurrentModificationException on the next next() call. With if (i == 2) instead it silently ends without error, because after removal size == cursor and hasNext() returns false. Use removeIf or Iterator.remove.
⚠ Follow-up traps
Why does l.remove(i) remove by value here?i is an Integer, so remove(Object) is chosen; with an int it would remove by index.
What if the list is List.of(1,2,3)?UnsupportedOperationException on remove.
#collections#concurrent-modification
Q72
Will this swap work?
basic
Trace the code below.
static void swap(int a, int b) { int t = a; a = b; b = t; }// main: int x = 1, y = 2; swap(x, y); System.out.println(x + " " + y);
It prints 1 2. The method swaps its own copies. The same applies to Integer parameters, since the references are copied.
⚠ Follow-up traps
How can you swap two values then? Return a pair, swap elements in an array/list, or use a mutable holder.
Does swapping array elements via swap(int[] arr, i, j) work? Yes, because the shared array object is mutated.
#pass-by-value#methods
Q73
What does the caller see?
basic
Trace the code below.
static void f(int[] a) { a[0] = 99; a = new int[]{7}; a[0] = 5; }// main: int[] arr = {1, 2}; f(arr); System.out.println(arr[0]);
99. The first write goes through the shared reference; the reassignment affects only the local copy of the reference.
⚠ Follow-up traps
Are arrays copied when passed? No, only the reference.
Is arr.clone() a deep copy for int[][]? No, it is shallow; the inner arrays are shared.
Strings are immutable: toUpperCase() returns a new string, which was discarded. Even s = s.toUpperCase() inside would only rebind the local parameter, so return the result and assign it in the caller.
⚠ Follow-up traps
Would a StringBuilder parameter behave differently? Yes, sb.append mutates the shared object.
Can IDEs warn about this? Yes, as an ignored return value.
#string#immutability
Q75
What compiles and what fails?
basic
Trace the code below.
final int[] a = {1, 2};a[0] = 9;a = new int[0];
a[0] = 9 compiles and works; a = new int[0] fails with "cannot assign a value to final variable a". final freezes the reference, not the array contents.
⚠ Follow-up traps
How to make the array contents read-only? Wrap in List.of/Collections.unmodifiableList or return copies.
Is a final local without initializer legal? Yes, if definitely assigned exactly once.
#final#arrays
Q76
Two threads each run `count++` 100,000 times on a `volatile int count`. What is the final value?
intermediate
Usually less than 200,000. count++ is three steps (read, add, write); volatile gives visibility but not atomicity, so updates are lost. Use AtomicInteger, LongAdder under contention, or synchronized.
⚠ Follow-up traps
Would synchronized on only the increment method fix it? Yes, if all accesses use the same lock.
Is a volatile write-only counter safe with a single writer? Yes, one writer thread plus volatile readers is a valid pattern.
Without volatile there is no happens-before between the write and the worker's reads, so the JIT may hoist the read out of the loop and the worker never sees false. Declare the flag volatile (or use AtomicBoolean, or interruption).
⚠ Follow-up traps
Does the bug show up in interpreter-only mode? Often not, which makes it hard to reproduce; it appears after JIT compilation.
Would System.out.println in the loop mask it? Yes, synchronization inside println accidentally establishes visibility.
#volatile#visibility#jmm
Q78
What are the field values after serializing and deserializing this object?
basic
Trace the code below.
class User implements Serializable { String name = "ann"; transient String password = "secret"; transient int attempts = 3;}
name is "ann", password is null, attempts is 0. Transient fields are skipped and get type defaults; field initializers do not run because the constructor of a Serializable class is not invoked.
⚠ Follow-up traps
How can you restore attempts to 3? Implement readObject or readResolve.
Is static state serialized? No.
#transient#serialization
Q79
Does this throw a `NullPointerException`?
intermediate
Trace the code below.
class T { static void hi() { System.out.println("hi"); } }// main: ((T) null).hi();
No, it prints hi. A static method is bound to the declared type at compile time; the null reference is never dereferenced (the expression is evaluated, then discarded). Call it as T.hi() to avoid confusion.
⚠ Follow-up traps
What if hi() were an instance method?NullPointerException.
Does the same hold for static fields? Yes, ((T) null).staticField reads the field.
#static#null
Q80
Which overload is called, and what if a third one is added?
String, the most specific applicable overload. If you add m(Integer i), m(null) fails to compile with "reference to m is ambiguous", since neither String nor Integer is more specific.
⚠ Follow-up traps
How do you disambiguate? Cast: m((String) null).
What if the declared variable is Object o = "x"; m(o);?Object; overloads use static types.
#overloading#null
Q81
Which overload runs for m(5) among long, Integer and varargs?
long. Resolution tries phase 1 (strict: widening, no boxing) first and int widens to long; boxing is phase 2 and varargs phase 3.
⚠ Follow-up traps
What if m(long) is removed?Integer.
What if both m(Integer) and m(int...) remain and the call is m()?varargs, the only applicable one.
#overloading#boxing
Q82
What do field, static method and instance method access print through a parent reference?
intermediate
Trace the code below.
class A { String n = "A"; static String s() { return "A"; } String i() { return "A"; } }class B extends A { String n = "B"; static String s() { return "B"; } String i() { return "B"; } }// A a = new B();// System.out.println(a.n + a.s() + a.i());
AAB. Fields and static methods are resolved by the declared type (A), only the instance method i() is dispatched dynamically.
⚠ Follow-up traps
Does B.s() override A.s()? No, it hides it.
Does @Override on s() in B compile? No, it is a compile error.
#polymorphism#static#hiding
Q83
Which of these `var` declarations compile?
intermediate
Trace the code below.
var a = 10;var list = new ArrayList<>();var n = null;var arr = {1, 2};var f = () -> 1;
Only the first two. a is int; list is ArrayList<Object>. var n = null has no inferable type, var arr = {1, 2} needs an explicit int[] or new int[]{...}, and a lambda has no target type.
⚠ Follow-up traps
Can you then assign a = "x"? No, the type is fixed as int.
What does var x = cond ? 1 : "s"; infer? An intersection type such as Serializable & Comparable<...>; usable but hard to read.
#var#type-inference
Q84
What does this print, and what does the record give you for free?
intermediate
Trace the code below.
record Person(String name, int age) { Person { if (age < 0) throw new IllegalArgumentException("age"); name = name.trim(); }}// var p = new Person(" Ann ", 30);// System.out.println(p + " " + p.equals(new Person("Ann", 30)));
Person[name=Ann, age=30] true. The compact constructor normalizes the parameter before the generated field assignment, and generated equals compares all components.
⚠ Follow-up traps
Can the compact constructor assign this.name? No, assigning fields is only allowed in a canonical (explicit) constructor.
Is p.getName() available? No, the accessor is p.name().
#records#equals
Q85
A record holds a `List`. Is it safe to share?
intermediate
Trace the code below.
record Team(List<String> members) {}var l = new ArrayList<String>(List.of("a"));var t = new Team(l);l.add("b");System.out.println(t.members().size());
Prints 2. Records are only shallowly immutable, so the caller's list is shared. Fix with a defensive copy in the compact constructor: members = List.copyOf(members);.
⚠ Follow-up traps
Does List.copyOf always copy? No, it returns the same instance if the input is already an immutable List.of-style list.
Does copyOf allow null elements? No, it throws NPE.
#records#immutability
Q86
How long is the string produced by each text block?
intermediate
Trace the code below.
String a = """ Hello World """;String b = """ Hello World""";
a is "Hello\n World\n" (length 14); b is "Hello\n World" (length 13). The closing delimiter's line participates in indentation stripping, and putting it on its own line adds the final newline.
⚠ Follow-up traps
What if the closing """ is indented less than the content? The extra indentation is retained in every line.
How do you keep trailing spaces? Use \s or \040.
#text-blocks#strings
Q87
Production throws `OutOfMemoryError: Java heap space`. How do you diagnose it?
intermediate
Capture evidence, then find what retains memory. Start with -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=... and GC logs (-Xlog:gc*).
Open the dump in Eclipse MAT or VisualVM; look at the dominator tree and "leak suspects".
Distinguish a leak (old gen grows after every full GC) from a sizing problem (live set simply exceeds -Xmx).
Use JFR allocation profiling to see where objects are created.
Raising -Xmx is a stopgap, not a fix.
⚠ Follow-up traps
What does GC overhead limit exceeded mean? The JVM spent over 98% of time in GC reclaiming under 2%; it is the same class of problem.
Is OOM always heap? No: Metaspace, direct memory, "unable to create native thread" and swap exhaustion are different.
#oom#heap#troubleshooting
Q88
Why does this crash with `StackOverflowError` and how do you fix it?
basic
Trace the code below.
static int depth(int n) { return depth(n + 1); }
There is no base case, so frames pile up until the thread stack (-Xss) is exhausted. Add a terminating condition; for legitimately deep recursion convert it to an iterative loop with an explicit stack. Java does not perform tail-call optimization.
⚠ Follow-up traps
Is StackOverflowError an Exception? No, it is an Error (a VirtualMachineError).
Does increasing -Xss fix infinite recursion? No, it only crashes later.
#stack#recursion
Q89
A Tomcat app throws `OutOfMemoryError: Metaspace` after several redeployments. Why?
advanced
Classloader leak. Each redeploy creates a new webapp class loader; if anything outside it still references one of its classes or the loader itself (a JDBC driver registered in DriverManager, a ThreadLocal, a thread started by the app, a static in a shared library), the whole loader and its classes stay in metaspace.
Find it via a heap dump: look for multiple instances of the webapp class loader and their GC root path.
Fix: deregister drivers, stop threads, clear ThreadLocals on shutdown.
⚠ Follow-up traps
Does -XX:MaxMetaspaceSize fix it? It only makes the failure earlier and predictable.
Can generated proxies cause the same error without redeploys? Yes, repeated dynamic class generation.
#metaspace#classloader#leak
Q90
This cache has no eviction. What goes wrong?
intermediate
Trace the code below.
static final Map<String, byte[]> CACHE = new HashMap<>();static byte[] get(String k) { return CACHE.computeIfAbsent(k, Loader::load); }
A static map is reachable from a GC root, so entries are never collected; with unbounded keys the heap fills and ends in OutOfMemoryError. Use a bounded cache with eviction (Caffeine, size/time based), or soft/weak references where semantics fit. HashMap is also not thread-safe here.
⚠ Follow-up traps
Does WeakHashMap solve it for String keys? Not for literals or interned keys that stay strongly reachable.
Why is ConcurrentHashMap.computeIfAbsent still risky? The loader runs under a bin lock; a slow or recursive load blocks others.
#memory-leak#static#cache
Q91
When does each object become eligible for GC?
basic
Trace the code below.
Object a = new Object();Object b = a;a = null;b = null;
After a = null the object is still reachable through b; after b = null there are no references and it becomes eligible (assuming no other path). Eligibility is not collection; the GC decides when to reclaim.
⚠ Follow-up traps
What about two objects referencing each other with no outside references? Both are eligible; Java uses tracing, not reference counting.
Does a JIT-compiled method keep a dead local alive? No, liveness analysis may release it before the variable goes out of scope.
#gc#reachability
Q92
A container limited to 1 GB runs `java -Xmx1g -jar app.jar` and is killed (OOMKilled). Why?
intermediate
The heap alone can use the full 1 GB, and the JVM also needs metaspace, thread stacks, code cache, direct buffers and GC structures, so the process exceeds the cgroup limit and the kernel kills it. Leave headroom: -XX:MaxRAMPercentage=60 to 75 (default is 25%), and cap -XX:MaxMetaspaceSize and -Xss where sensible.
⚠ Follow-up traps
Does the JVM see the container limit? Yes since Java 10 (8u191) with UseContainerSupport enabled by default.
Is Java OOM the same as OOMKilled? No: OOMKilled is the OS killing the process, with no Java exception and no heap dump.
#containers#memory#jvm-flags
Q93
A hand-rolled benchmark shows the first call taking 50 ms and later calls 0.2 ms. What is happening?
intermediate
Class loading, interpretation and tiered JIT compilation. Early calls run in the interpreter, then C1, then C2-optimized code. Naive timing with System.nanoTime also suffers from dead-code elimination and constant folding. Use JMH, which handles warm-up, forks and Blackhole.
⚠ Follow-up traps
Can you warm up in production? Yes, with synthetic traffic at startup, CDS/AOT-style approaches or GraalVM native image (Project Leyden is in progress).
Does deoptimization reset the warm-up? Yes, an invalidated assumption sends code back to the interpreter.
#jit#benchmarking#warmup
Q94
What do mixed integer and double division and remainder expressions print?
0.0, 1.5, -2 -2 2, 1. Integer division truncates toward zero, evaluation is left to right so 1 / 2 is 0 before the double multiplication, and % takes the sign of the dividend; floorMod takes the sign of the divisor.
⚠ Follow-up traps
What is Math.floorDiv(-5, 2)?-3.
What identity links / and %?(a / b) * b + a % b == a.
#arithmetic#division
Q95
What do integer and floating-point division by zero produce?
The first throws ArithmeticException: / by zero and nothing after it runs. Floating-point forms give Infinity, NaN and NaN respectively. Integer remainder by zero also throws.
⚠ Follow-up traps
What is -1.0 / 0?-Infinity.
What does (int) Double.NaN give?0.
#arithmetic#floating-point
Q96
How do NaN and signed zero behave with `==` versus `equals`?
advanced
Trace the code below.
double nan = Double.NaN;System.out.println(nan == nan);System.out.println(Double.valueOf(nan).equals(nan));System.out.println(0.0 == -0.0);System.out.println(Double.valueOf(0.0).equals(-0.0));
false, true, true, false. Primitive == follows IEEE 754 (NaN is unequal to itself, 0.0 equals -0.0); Double.equals compares the bit patterns (canonicalized NaN), so it is consistent with compare and hash codes.
⚠ Follow-up traps
How do you test for NaN?Double.isNaN(x).
What happens to a NaN key in a HashMap<Double,?>? It works, because equals treats NaNs as equal.
#floating-point#equality
Q97
What do compound assignment and array-index evaluation order print?
advanced
Trace the code below.
int x = 5;x += x++ * 2;System.out.println(x);int[] a = {0, 0};int i = 0;a[i] = i = 1;System.out.println(Arrays.toString(a));
15 and [1, 0]. Java evaluates left to right: x += ... saves the left value 5 first, x++ * 2 is 5 * 2 = 10, and the result 15 overwrites the incremented x. For the array, the index a[i] is evaluated first (i was 0), then the right side assigns i = 1, so element 0 gets 1.
⚠ Follow-up traps
Is evaluation order undefined as in C? No, Java specifies operand evaluation left to right.
Does precedence determine evaluation order? No, precedence only determines grouping.
2, -4, 15, 8589934592. The int shift distance is masked to 5 bits (33 & 31 = 1); >> keeps the sign; -8 is 0xFFFFFFF8, and a logical shift by 28 leaves 0xF.
⚠ Follow-up traps
What does >>> do on byte b = -1; b >>>= 4;?b is promoted to int (0xFFFFFFFF), shifted to 0x0FFFFFFF, and narrowed back to byte as -1.
How do you check whether n is a power of two?n > 0 && (n & (n - 1)) == 0.
#bitwise#operators
Q99
What does mixing `Long` and `int` in `equals` and `contains` print?
advanced
Trace the code below.
Long l = 127L;System.out.println(l.equals(127));System.out.println(l.equals(127L));System.out.println(l == 127);Set<Long> s = new HashSet<>(List.of(1L));System.out.println(s.contains(1));
false, true, true, false. l.equals(127) boxes to Integer, and Long.equals requires a Long; l == 127 unboxes l and compares numerically; contains(1) boxes an Integer, so it never matches a Long.
⚠ Follow-up traps
How to look up by a numeric long safely? Use 1L.
Do other collections suffer the same? Yes, Map<Long,?>.get(1) returns null.
#autoboxing#equals
Q100
What does `Math.abs(Integer.MIN_VALUE)` return, and why does it break hash bucket code?
advanced
-2147483648, because +2147483648 does not fit in an int. Code like Math.abs(key.hashCode()) % n can therefore produce a negative index for a hash of Integer.MIN_VALUE. Use Math.floorMod(hash, n) or (hash & 0x7fffffff) % n.
⚠ Follow-up traps
Does Math.absExact exist? Yes since Java 15; it throws ArithmeticException for this case.
What is Integer.MIN_VALUE == -Integer.MIN_VALUE?true.
#overflow#math
Q101
What is the difference between `ClassNotFoundException` and `NoClassDefFoundError`?
intermediate
ClassNotFoundException is a checked exception thrown when explicit loading by name fails (Class.forName, loadClass). NoClassDefFoundError is an Error thrown when a class that was present at compile time cannot be found or initialized at runtime, such as a missing dependency jar or a failed static initializer earlier.
⚠ Follow-up traps
Which one appears from a simple new Foo() when the jar is missing?NoClassDefFoundError.
Is NoSuchMethodError the same class of problem? Related: a binary-incompatible version of a dependency at runtime.
#class-loading#errors
Q102
What happens when a static initializer fails?
advanced
Trace the code below.
class Config { static final int V = 1 / Integer.parseInt("0"); }// first use of Config.V, then second use
The first access throws ExceptionInInitializerError wrapping the ArithmeticException. The class is marked erroneous, so every later access throws NoClassDefFoundError: Could not initialize class Config, hiding the root cause that is only in the first stack trace.
⚠ Follow-up traps
Is the initializer retried? No, never within the same class loader.
Why is the first failure often missing from logs? It may have been swallowed or logged far earlier; search logs for ExceptionInInitializerError.
#class-loading#initialization#errors
Q103
What do `Math.round` and narrowing casts give for edge values?
-2 3, 3 -3, 2147483647 0. Math.round is floor(x + 0.5), so ties go toward positive infinity; casting to int truncates toward zero and saturates out-of-range values, with NaN becoming 0.
⚠ Follow-up traps
What about Math.rint(2.5)?2.0, round-half-even.
Does (long) 1e20 saturate? Yes, to Long.MAX_VALUE.
#casting#rounding
Q104
Why does `Math.round(x * 100) / 100` not give two decimals?
intermediate
Trace the code below.
double x = 2.567;System.out.println(Math.round(x * 100) / 100);
It prints 3. Math.round(double) returns a long, so dividing by 100 is integer division and truncates. Divide by 100.0 to get 2.57, or better use BigDecimal.setScale(2, RoundingMode.HALF_UP) for money.
⚠ Follow-up traps
What does Math.round(float) return? An int.
Is Math.round(2.675 * 100) / 100.0 reliable for decimals? No; 2.675 is not exactly representable, so use BigDecimal from a string.