Skip to main content

Scope, Loops, and Types

Source: Effective Java, 3rd Edition — Chapter 9 by Joshua Bloch (Items 57–62)

Chapter 9 covers everyday Java craft: variable scope, iteration, standard libraries, exact arithmetic, primitives vs boxes, and choosing the right types over strings.

Item 57: Minimize the scope of local variables​

Declare locals where first used, with an initializer when possible. Premature declaration widens scope and adds clutter.

Prefer for loops that declare loop variables in the header — scope ends with the loop, preventing copy-paste bugs like reusing i from an earlier while:

for (Iterator<Element> i = c.iterator(); i.hasNext(); ) {
Element e = i.next();
}

Keep methods small so unrelated locals don’t share scope. Exception: variables used after a try block may need declaration before try if initialization can throw checked exceptions.

Quiz

Local variable scope

1 / 2

A method declares Result r; at the top, then finally assigns it 40 lines later inside an if/else

Pick an answer to see if you are right.

Item 58: Prefer for-each loops to traditional for loops​

Enhanced for (for (Element e : c)) removes iterator/index clutter and works for collections, arrays, and anything Iterable:

for (Suit suit : suits)
for (Rank rank : ranks)
deck.add(new Card(suit, rank));

Avoid nested iterator loops that call next() on the outer iterator inside the inner loop (52-card deck bug).

When for-each won’t work: destructive filtering (Iterator.remove, or removeIf), in-place transform (list iterator / index), parallel iteration across collections. Then use explicit for/Iterator carefully.

Quiz

For-each vs iterators

1 / 2

Nested iterators: inner loop calls i.next() on outer iterator

Pick an answer to see if you are right.

Item 59: Know and use the libraries​

Don’t reinvent Random.nextInt(bound) with Math.abs(rnd.nextInt()) % n — bias, bad periods, and rare negative results.

Prefer ThreadLocalRandom.current().nextInt(bound) (Java 7+) for general use; SplittableRandom for parallel/fork-join. Use Objects, Collections, java.util.concurrent, streams — experts already debugged them.

Item 60: Avoid float and double if exact answers are required​

double cannot represent 0.1 exactly — money math drifts (1.03 - 0.42, candy-shopping loops).

For exact decimal needs:

  • BigDecimal with String constructors (not double ctor)
  • int/long cents (or smallest currency unit) when range allows

Use float/double for science/engineering approximations, not ledgers.

Item 61: Prefer primitive types to boxed primitives​

Primitives vs boxes differ in identity, null, and performance.

Broken comparator: (i == j) compares references. Use Integer.compare(a, b) or compare unboxed int values.

Integer i; if (i == 42) → NPE on unboxing. Long sum = 0L in a tight loop → boxing churn.

Use boxes when required: collections, generics, reflection.

Item 62: Avoid strings where other types are more appropriate​

Strings fit text. Don’t use them as:

  • Numbers → parse to int, BigDecimal, etc.
  • Enums → use enum types (Item 34)
  • Aggregates → small classes, not "className#index" keys
  • Capabilities → unforgeable keys (ThreadLocal.Key), not global string namespaces

ThreadLocal<T> replaced string-keyed thread locals with type-safe, fast instances.

Quiz

Strings vs other types

1 / 2

ThreadLocal.set(String key, Object value) with client-chosen keys

Pick an answer to see if you are right.

Items 57–62 map​

ItemMove
57Declare locals late; for-loop scope
58for-each when you only need elements
59Use library experts — Random.nextInt, etc.
60BigDecimal or int cents for exact money
61Primitives in hot paths; Integer.compare
62Parse/enums/classes — not string everything

Next: Performance, Reflection, and Style (Items 63–68).