Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Part 1: JVM Memory, Types & Fundamentals
JAVA

Part 1: JVM Memory, Types & Fundamentals

Revise the JVM memory model, primitive types, objects, operators, control flow, and the Java String pool.

1. JVM Memory Model

  • Stack — one frame per method call; holds local variables, primitive values, and references to heap objects. Stack lives and dies with the method call.
  • Heap — the single shared area where all objects and arrays live; shared by all threads. Managed by the garbage collector.
  • Metaspace (Java 8+) — stores class metadata and static variables; replaced PermGen. No size cap by default.
  • Method area — a logical part of Metaspace holding class definitions, constant pools, and method bytecode.
  • Gotcha: local primitives are on the stack, but any object (including Integer, String) is on the heap — only the reference sits on the stack.

2. Primitives vs Reference Types

PrimitiveSizeDefault
byte1 byte0
short2 bytes0
int4 bytes0
long8 bytes0L
float4 bytes0.0f
double8 bytes0.0d
char2 bytes (unsigned)'\u0000'
boolean1 bit (JVM-dep)false
  • Primitives are value types — copied by value, compared with ==.
  • Reference types are objects — the variable holds an address; == on references compares addresses unless overridden (or for the special wrapper cases below).
  • Exact comparison trap: == on two Integer objects compares references, but JVM caches Integer in [-128, 127] — so Integer a=100, b=100; a==b is true, but Integer c=200, d=200; c==d is false. Always use .equals() for wrappers.

Boxing & unboxing

  • Autoboxing wraps a primitive into its wrapper (int → Integer); unboxing unwraps it.
  • Integer i = null; int x = i; throws NullPointerException at unboxing.

3. Operators & Precedence

  • == vs .equals(): == compares references (or primitives), .equals() compares logical content (overridden in classes like String, wrapper, Collections).
  • && vs &: && short-circuits; & also evaluates the right side (and can be bitwise).
  • || vs |: same rule — || short-circuits.
  • ++i (pre) vs i++ (post): pre increments first, then returns; post returns the old value first, then increments. In int y = i++ + i++; evaluation is left-to-right with the reads — classic output trap.
  • instanceof: tests whether a reference is a subtype or implementation.
  • Ternary ? : evaluates only the chosen branch (unlike &/| which evaluate both).

Precedence (high → low): ++/--/unary > () method call > *///%, +/- > shift / > relational </>/<=/>= > equality ==/!= > & > ^ > | > && > || > ternary > assignment. Rely on parentheses in code — precedence questions are the #1 trap.

4. Control Flow

  • switch on int/char/String/enum (and wrapper types) — cases are constants; break prevents fall-through (Java 12+ switch expressions with arrows/yield).
  • for vs enhanced for: enhanced for (int v : list) internally uses the iterator; removing while iterating throws ConcurrentModificationException unless you use iterator.remove() or ListIterator.
  • try/catch/finally: finally always runs (unless System.exit or JVM crash). return inside try executes, then finally, then returns — a return in finally overrides the try-return.
  • Labeled loops outer:break outer; exits the outer loop.

Gotcha: floating-point equality in switch is not allowed; comparing floats with == after arithmetic is unreliable.

5. Strings at Interview Speed

  • String pool (interned): literals like "hi" are interned; new String("hi") creates a heap object not in the pool (unless .intern()).
  • String equals: content.equals() overridden, so new String("a").equals("a")true, but new String("a") == "a"false.
  • String immutability — reasons: thread-safety, hash caching, security, classloader safety.
  • StringBuilder: mutable, unsynchronized (fast — use in a single thread); StringBuffer: synchronised (slow, for multithreaded).
  • String.concat() vs +: + is compiled to StringBuilder under the hood, so chained + in a loop creates wasted builders — use explicit StringBuilder in loops.
String a = "ab";
String b = "ab";
System.out.println(a == b);           // true (same interned literal)
String c = new String("ab");
System.out.println(a == c);           // false (different reference)
System.out.println(a.equals(c));      // true (content)
final String x = "a";                 // compile-time constant
String y = x + "b";                   // interns like "ab"
System.out.println(y == a);           // true

My Private Notes

Notes are auto-saved locally to this device.