Learning goals
Model fixed sets of constants with enums, attach behavior and fields to enum constants, and use nested types (static vs inner) without memory leaks or confusing syntax.
Basic enums
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Day today = Day.MONDAY;
if (today == Day.SATURDAY) { ... }
Enums are classes extending java.lang.Enum—singleton instances, type-safe constants. Prefer over public static final int magic numbers.
switch (today) {
case MONDAY -> System.out.println("Start");
case FRIDAY -> System.out.println("Almost weekend");
default -> { }
}
Enums with fields and methods
public enum Planet {
EARTH(5.972e24, 6.371e6),
MARS(6.39e23, 3.389e6);
private final double massKg;
private final double radiusM;
Planet(double massKg, double radiusM) {
this.massKg = massKg;
this.radiusM = radiusM;
}
public double surfaceGravity() {
double G = 6.674e-11;
return G * massKg / (radiusM * radiusM);
}
}
Each constant calls its constructor once at class load.
Enum methods
public enum Status {
PENDING, ACTIVE, CLOSED;
public boolean isOpen() {
return this == ACTIVE || this == PENDING;
}
public static Status fromCode(String code) {
return switch (code) {
case "P" -> PENDING;
case "A" -> ACTIVE;
case "C" -> CLOSED;
default -> throw new IllegalArgumentException(code);
};
}
}
values() and valueOf(String) are generated—parse carefully with validation.
Enum implementing interfaces
public enum Op implements Calculator {
PLUS {
public int apply(int a, int b) { return a + b; }
},
MINUS {
public int apply(int a, int b) { return a - b; }
};
public abstract int apply(int a, int b);
}
Strategy pattern with fixed set of implementations.
Nested classes
Static nested — does not capture outer instance:
public class Outer {
static class Nested {
void hello() { System.out.println("nested"); }
}
}
Outer.Nested n = new Outer.Nested();
Inner class — holds implicit reference to outer:
public class Outer {
private int value = 42;
class Inner {
void print() {
System.out.println(value); // Outer.this.value
}
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
Local and anonymous classes
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("once");
}
};
Lambdas replace many anonymous classes for SAM interfaces:
Runnable r2 = () -> System.out.println("once");
When to use nested types
| Type | Use |
|---|---|
| Static nested | Helper grouped with outer; no outer state |
| Inner | Needs outer instance state; iterator pattern |
| Local | Tiny one-off inside method (rare with lambdas) |
| Enum | Fixed constant set with behavior |
Common mistakes
enumwith public mutable fields — treat constants as immutable.- Inner class in static context without outer instance — need
outer.new Inner(). - Memory leak: non-static inner held long-lived — inner retains outer; prefer static nested + weak ref if needed.
- Ordinal for business logic —
ordinal()breaks when reordering; use explicit fields. - Switch on enum without default — exhaustiveness OK for enums, but handle new enum values when evolving API.
Practice checkpoint
-
Define
Priority { LOW, MEDIUM, HIGH }with methodisHigh().- Answer:
return this == HIGH;
- Answer:
-
Difference static nested vs inner?
- Answer: Static has no outer reference; inner requires outer instance.
-
Safe parse:
Day.valueOf("MON")?- Answer: Throws
IllegalArgumentException; validate input.
- Answer: Throws
-
Replace anonymous
Comparatorwith lambda.- Answer:
(a, b) -> Integer.compare(a.size(), b.size())
- Answer:
Interview angles
- “Enum singleton?” — Effective singleton pattern (Joshua Bloch); serialization-safe.
- “Can enum extend class?” — No (extends Enum implicitly); can implement interfaces.
- “Why static nested for Builder?” — Builder doesn’t need enclosing instance; avoids extra reference.