Performance, Reflection, and Style
Source: Effective Java, 3rd Edition — Chapter 9 by Joshua Bloch (Items 63–68)
This lesson closes Chapter 9: building strings efficiently, programming to interfaces, limited reflection, native methods, optimization discipline, and Java naming conventions.
Item 63: Beware the performance of string concatenation
+ on strings is fine for a few pieces, but repeated concatenation in a loop is O(n²) — each + copies both operands because strings are immutable.
// Bad in a loop
String result = "";
for (int i = 0; i < n; i++)
result += lineForItem(i);
// Good
StringBuilder b = new StringBuilder(n * LINE_WIDTH);
for (int i = 0; i < n; i++)
b.append(lineForItem(i));
return b.toString();
Pre-size StringBuilder when you know approximate length. For many strings, also consider joining in one pass without building one giant intermediate string per step.
Item 64: Refer to objects by their interfaces
Declare variables, parameters, return types, and fields with the interface when one exists. Use the implementation class only in new:
Set<Son> sons = new LinkedHashSet<>();
Then switching LinkedHashSet → HashSet doesn’t break callers. Exception: code that depends on implementation-specific behavior (e.g. LinkedHashSet iteration order) must keep that type.
When no interface fits: value classes (String, BigInteger), framework base classes (OutputStream), or types with extra methods not on the interface (PriorityQueue.comparator()).
Program to interfaces
1 / 2Field is HashMap<K,V>; you only need Map operations and may swap to EnumMap later
Pick an answer to see if you are right.
Item 65: Prefer interfaces to reflection
Reflection (Class.forName, Constructor.newInstance, Method.invoke) can touch classes unknown at compile time, but costs compile-time checking, readability, and speed (~11× slower for a trivial invoke in Bloch’s tests).
Limited pattern: reflect only to construct objects; use them through a known interface or superclass afterward:
Class<? extends Set<String>> cl = (Class<? extends Set<String>>) Class.forName(args[0]);
Set<String> s = cl.getDeclaredConstructor().newInstance();
s.addAll(...); // normal Set usage from here
Catch ReflectiveOperationException (Java 7+) to shrink catch blocks. If you don’t need runtime class loading, skip reflection.
Item 66: Use native methods judiciously
JNI calls C/C++ code. Legitimate uses: platform-specific APIs, legacy native libraries, and rare extreme performance (e.g. GMP for huge BigInteger-scale math).
Downsides: no memory safety, weaker portability, harder debugging, GC can’t track native memory well, JNI transition cost. JVM and Java libraries closed most old “must go native for speed” gaps (BigInteger reimplemented in Java beat its C version).
Default: stay in Java unless a vetted native library clearly wins.
Native methods
1 / 2Primary reason to avoid JNI for routine hot loops today
Pick an answer to see if you are right.
Item 67: Optimize judiciously
Don’t optimize prematurely. Write clear, well-structured programs first; profile before tuning.
- Rule 1: Don’t do it.
- Rule 2 (experts): Don’t do it yet — not until you have a clean baseline.
- Rule 3: Measure before and after each change.
Think about performance at design time for hard-to-change surfaces: APIs, wire protocols, persistent formats. A mutable Dimension return from Component.getSize() forces allocations forever.
Fix algorithmic problems (quadratic string concat, wrong data structure) before micro-optimizing. Use profilers and JMH for microbenchmarks — Java’s cost model varies by JVM and hardware.
Optimization discipline
1 / 2statement() builds a large report with += in a loop
Pick an answer to see if you are right.
Item 68: Adhere to generally accepted naming conventions
Typographical (JLS §6.1):
| Kind | Style | Example |
|---|---|---|
| Package | lowercase, reversed domain | com.google.common.collect |
| Class / interface | PascalCase | HttpClient, FutureTask |
| Method / field | camelCase | remove, ensureCapacity |
| Constant | UPPER_SNAKE | MAX_VALUE (static final immutable) |
| Type parameter | single letter | T, E, K, V |
Grammatical: classes are singular nouns (Thread); utility classes often plural (Collections); interfaces like classes or …able; action methods are verbs; boolean accessors often is/has (isEmpty); getters may be getTime or time().
Break conventions only when long-established usage says otherwise.
Naming conventions
1 / 2static final int maxConnections = 10;
Pick an answer to see if you are right.
Items 63–68 map
| Item | Move |
|---|---|
| 63 | StringBuilder for many concatenations |
| 64 | Set in types; LinkedHashSet in new |
| 65 | Reflect to construct; interface for everything else |
| 66 | JNI only when Java libraries aren’t enough |
| 67 | Profile; fix algorithms; measure changes |
| 68 | JLS naming — packages, classes, constants, booleans |
Chapter 9 complete. Next: Exceptions (Chapter 10, Items 69–73).