@booklib/skills 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/animation-at-work/SKILL.md +246 -0
- package/animation-at-work/assets/example_asset.txt +1 -0
- package/animation-at-work/references/api_reference.md +369 -0
- package/animation-at-work/references/review-checklist.md +79 -0
- package/animation-at-work/scripts/example.py +1 -0
- package/bin/skills.js +85 -0
- package/clean-code-reviewer/SKILL.md +292 -0
- package/clean-code-reviewer/evals/evals.json +67 -0
- package/data-intensive-patterns/SKILL.md +204 -0
- package/data-intensive-patterns/assets/example_asset.txt +1 -0
- package/data-intensive-patterns/references/api_reference.md +34 -0
- package/data-intensive-patterns/references/patterns-catalog.md +551 -0
- package/data-intensive-patterns/references/review-checklist.md +193 -0
- package/data-intensive-patterns/scripts/example.py +1 -0
- package/data-pipelines/SKILL.md +252 -0
- package/data-pipelines/assets/example_asset.txt +1 -0
- package/data-pipelines/references/api_reference.md +301 -0
- package/data-pipelines/references/review-checklist.md +181 -0
- package/data-pipelines/scripts/example.py +1 -0
- package/design-patterns/SKILL.md +245 -0
- package/design-patterns/assets/example_asset.txt +1 -0
- package/design-patterns/references/api_reference.md +1 -0
- package/design-patterns/references/patterns-catalog.md +726 -0
- package/design-patterns/references/review-checklist.md +173 -0
- package/design-patterns/scripts/example.py +1 -0
- package/domain-driven-design/SKILL.md +221 -0
- package/domain-driven-design/assets/example_asset.txt +1 -0
- package/domain-driven-design/references/api_reference.md +1 -0
- package/domain-driven-design/references/patterns-catalog.md +545 -0
- package/domain-driven-design/references/review-checklist.md +158 -0
- package/domain-driven-design/scripts/example.py +1 -0
- package/effective-java/SKILL.md +195 -0
- package/effective-java/assets/example_asset.txt +1 -0
- package/effective-java/references/api_reference.md +1 -0
- package/effective-java/references/items-catalog.md +955 -0
- package/effective-java/references/review-checklist.md +216 -0
- package/effective-java/scripts/example.py +1 -0
- package/effective-kotlin/SKILL.md +225 -0
- package/effective-kotlin/assets/example_asset.txt +1 -0
- package/effective-kotlin/references/api_reference.md +1 -0
- package/effective-kotlin/references/practices-catalog.md +1228 -0
- package/effective-kotlin/references/review-checklist.md +126 -0
- package/effective-kotlin/scripts/example.py +1 -0
- package/kotlin-in-action/SKILL.md +251 -0
- package/kotlin-in-action/assets/example_asset.txt +1 -0
- package/kotlin-in-action/references/api_reference.md +1 -0
- package/kotlin-in-action/references/practices-catalog.md +436 -0
- package/kotlin-in-action/references/review-checklist.md +204 -0
- package/kotlin-in-action/scripts/example.py +1 -0
- package/lean-startup/SKILL.md +250 -0
- package/lean-startup/assets/example_asset.txt +1 -0
- package/lean-startup/references/api_reference.md +319 -0
- package/lean-startup/references/review-checklist.md +137 -0
- package/lean-startup/scripts/example.py +1 -0
- package/microservices-patterns/SKILL.md +179 -0
- package/microservices-patterns/references/patterns-catalog.md +391 -0
- package/microservices-patterns/references/review-checklist.md +169 -0
- package/package.json +17 -0
- package/refactoring-ui/SKILL.md +236 -0
- package/refactoring-ui/assets/example_asset.txt +1 -0
- package/refactoring-ui/references/api_reference.md +355 -0
- package/refactoring-ui/references/review-checklist.md +114 -0
- package/refactoring-ui/scripts/example.py +1 -0
- package/storytelling-with-data/SKILL.md +238 -0
- package/storytelling-with-data/assets/example_asset.txt +1 -0
- package/storytelling-with-data/references/api_reference.md +379 -0
- package/storytelling-with-data/references/review-checklist.md +111 -0
- package/storytelling-with-data/scripts/example.py +1 -0
- package/system-design-interview/SKILL.md +213 -0
- package/system-design-interview/assets/example_asset.txt +1 -0
- package/system-design-interview/references/api_reference.md +582 -0
- package/system-design-interview/references/review-checklist.md +201 -0
- package/system-design-interview/scripts/example.py +1 -0
- package/using-asyncio-python/SKILL.md +242 -0
- package/using-asyncio-python/assets/example_asset.txt +1 -0
- package/using-asyncio-python/references/api_reference.md +267 -0
- package/using-asyncio-python/references/review-checklist.md +149 -0
- package/using-asyncio-python/scripts/example.py +1 -0
- package/web-scraping-python/SKILL.md +259 -0
- package/web-scraping-python/assets/example_asset.txt +1 -0
- package/web-scraping-python/references/api_reference.md +393 -0
- package/web-scraping-python/references/review-checklist.md +163 -0
- package/web-scraping-python/scripts/example.py +1 -0
|
@@ -0,0 +1,955 @@
|
|
|
1
|
+
# Effective Java Items Catalog
|
|
2
|
+
|
|
3
|
+
Complete reference for all 90 items from Joshua Bloch's *Effective Java* (3rd Edition),
|
|
4
|
+
organized by chapter. Use this catalog when generating or reviewing Java code to identify
|
|
5
|
+
which items apply.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Chapter 2: Creating and Destroying Objects
|
|
10
|
+
|
|
11
|
+
### Item 1: Consider static factory methods instead of constructors
|
|
12
|
+
|
|
13
|
+
Static factory methods have advantages over constructors: they have names, don't require
|
|
14
|
+
creating a new object on each invocation, can return subtypes, and the returned type can
|
|
15
|
+
vary based on input parameters.
|
|
16
|
+
|
|
17
|
+
**Naming conventions**: `from`, `of`, `valueOf`, `instance`/`getInstance`, `create`/`newInstance`, `getType`, `newType`, `type`
|
|
18
|
+
|
|
19
|
+
**Anti-pattern**:
|
|
20
|
+
```java
|
|
21
|
+
// Direct constructor — no name, always creates new instance
|
|
22
|
+
BigInteger prime = new BigInteger("7");
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct**:
|
|
26
|
+
```java
|
|
27
|
+
// Named, can cache, can return subtype
|
|
28
|
+
BigInteger prime = BigInteger.valueOf(7);
|
|
29
|
+
List<String> empty = List.of();
|
|
30
|
+
Optional<String> opt = Optional.empty();
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### Item 2: Consider a builder when faced with many constructor parameters
|
|
36
|
+
|
|
37
|
+
The Builder pattern simulates named optional parameters. Use it when constructors would
|
|
38
|
+
need 4+ parameters, especially if many are optional or of the same type.
|
|
39
|
+
|
|
40
|
+
**Anti-pattern** (telescoping constructors):
|
|
41
|
+
```java
|
|
42
|
+
NutritionFacts nf = new NutritionFacts(240, 8, 100, 0, 35, 27);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Correct** (Builder):
|
|
46
|
+
```java
|
|
47
|
+
NutritionFacts nf = new NutritionFacts.Builder(240, 8)
|
|
48
|
+
.calories(100)
|
|
49
|
+
.sodium(35)
|
|
50
|
+
.carbohydrate(27)
|
|
51
|
+
.build();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Key points**: Builder can enforce invariants in `build()`. Builder works well with class hierarchies using recursive type parameters (covariant return typing).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### Item 3: Enforce the singleton property with a private constructor or an enum type
|
|
59
|
+
|
|
60
|
+
For singletons, prefer a single-element enum which provides serialization for free and
|
|
61
|
+
guarantees against multiple instantiation even in the face of reflection attacks.
|
|
62
|
+
|
|
63
|
+
**Preferred**:
|
|
64
|
+
```java
|
|
65
|
+
public enum Elvis {
|
|
66
|
+
INSTANCE;
|
|
67
|
+
public void leaveTheBuilding() { ... }
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Alternative** (when you need to extend a superclass):
|
|
72
|
+
```java
|
|
73
|
+
public class Elvis {
|
|
74
|
+
private static final Elvis INSTANCE = new Elvis();
|
|
75
|
+
private Elvis() { }
|
|
76
|
+
public static Elvis getInstance() { return INSTANCE; }
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### Item 4: Enforce noninstantiability with a private constructor
|
|
83
|
+
|
|
84
|
+
Utility classes (collections of static methods) should not be instantiable.
|
|
85
|
+
|
|
86
|
+
```java
|
|
87
|
+
public class UtilityClass {
|
|
88
|
+
private UtilityClass() {
|
|
89
|
+
throw new AssertionError(); // Prevents internal instantiation
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### Item 5: Prefer dependency injection to hardwiring resources
|
|
97
|
+
|
|
98
|
+
Don't use a singleton or static utility class to implement a class that depends on
|
|
99
|
+
underlying resources. Pass the resource (or a factory) into the constructor.
|
|
100
|
+
|
|
101
|
+
**Anti-pattern**:
|
|
102
|
+
```java
|
|
103
|
+
public class SpellChecker {
|
|
104
|
+
private static final Lexicon dictionary = new EnglishLexicon(); // Hardwired
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Correct**:
|
|
109
|
+
```java
|
|
110
|
+
public class SpellChecker {
|
|
111
|
+
private final Lexicon dictionary;
|
|
112
|
+
public SpellChecker(Lexicon dictionary) {
|
|
113
|
+
this.dictionary = Objects.requireNonNull(dictionary);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### Item 6: Avoid creating unnecessary objects
|
|
121
|
+
|
|
122
|
+
Reuse immutable objects. Prefer primitives to boxed primitives. Watch out for unintentional autoboxing in loops.
|
|
123
|
+
|
|
124
|
+
**Anti-pattern**:
|
|
125
|
+
```java
|
|
126
|
+
Long sum = 0L;
|
|
127
|
+
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
|
|
128
|
+
sum += i; // Creates ~2^31 unnecessary Long instances
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Correct**:
|
|
133
|
+
```java
|
|
134
|
+
long sum = 0L; // primitive
|
|
135
|
+
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
|
|
136
|
+
sum += i;
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Also: prefer `String s = "literal"` over `new String("literal")`. Cache expensive objects like `Pattern`.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### Item 7: Eliminate obsolete object references
|
|
145
|
+
|
|
146
|
+
Null out references when they become obsolete, especially in classes that manage their own
|
|
147
|
+
memory (stacks, caches, pools). Use `WeakHashMap` for caches, `LinkedHashMap.removeEldestEntry` for bounded caches.
|
|
148
|
+
|
|
149
|
+
**Key situations**: stack pop (null out popped element), cache entries, listener/callback registrations.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Item 8: Avoid finalizers and cleaners
|
|
154
|
+
|
|
155
|
+
Finalizers are unpredictable, dangerous, and generally unnecessary. Cleaners (Java 9) are
|
|
156
|
+
less dangerous but still unpredictable. Use `try-with-resources` and `AutoCloseable` instead.
|
|
157
|
+
|
|
158
|
+
**Exception**: Safety net for native resources, and `Cleaner` as backup only.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Item 9: Prefer try-with-resources to try-finally
|
|
163
|
+
|
|
164
|
+
Always use try-with-resources for any object that implements `AutoCloseable`.
|
|
165
|
+
|
|
166
|
+
**Anti-pattern**:
|
|
167
|
+
```java
|
|
168
|
+
InputStream in = new FileInputStream(src);
|
|
169
|
+
try {
|
|
170
|
+
// use in
|
|
171
|
+
} finally {
|
|
172
|
+
in.close(); // Can mask original exception
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Correct**:
|
|
177
|
+
```java
|
|
178
|
+
try (InputStream in = new FileInputStream(src);
|
|
179
|
+
OutputStream out = new FileOutputStream(dst)) {
|
|
180
|
+
// use in and out
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Chapter 3: Methods Common to All Objects
|
|
187
|
+
|
|
188
|
+
### Item 10: Obey the general contract when overriding equals
|
|
189
|
+
|
|
190
|
+
The `equals` contract: reflexive, symmetric, transitive, consistent, non-null.
|
|
191
|
+
Don't override `equals` unless you need logical equality. Use `instanceof` (not `getClass`) for type checking when the class is not designed for subclassing.
|
|
192
|
+
|
|
193
|
+
**Key recipe**: Check `this == obj`, check `instanceof`, cast, compare significant fields.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Item 11: Always override hashCode when you override equals
|
|
198
|
+
|
|
199
|
+
If two objects are equal according to `equals`, they must have the same `hashCode`.
|
|
200
|
+
Use `Objects.hash(field1, field2, ...)` for simple cases; compute manually for performance-critical code.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### Item 12: Always override toString
|
|
205
|
+
|
|
206
|
+
Provide a useful `toString` for debugging. Include all interesting information.
|
|
207
|
+
Document the format (or state that it's unspecified).
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Item 13: Override clone judiciously
|
|
212
|
+
|
|
213
|
+
Prefer copy constructors or copy factory methods to `Cloneable`. The `Cloneable` interface
|
|
214
|
+
is deeply flawed — it modifies `Object.clone()` behavior via an extralinguistic mechanism.
|
|
215
|
+
|
|
216
|
+
**Prefer**:
|
|
217
|
+
```java
|
|
218
|
+
public Yum(Yum yum) { ... } // Copy constructor
|
|
219
|
+
public static Yum newInstance(Yum yum) { ... } // Copy factory
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### Item 14: Consider implementing Comparable
|
|
225
|
+
|
|
226
|
+
Implement `Comparable` for value classes with natural ordering. Use `Comparator.comparing`
|
|
227
|
+
with chained `thenComparing` for clean, type-safe comparisons.
|
|
228
|
+
|
|
229
|
+
```java
|
|
230
|
+
private static final Comparator<PhoneNumber> COMPARATOR =
|
|
231
|
+
Comparator.comparingInt((PhoneNumber pn) -> pn.areaCode)
|
|
232
|
+
.thenComparingInt(pn -> pn.prefix)
|
|
233
|
+
.thenComparingInt(pn -> pn.lineNum);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Never** use difference-based comparators (e.g., `return o1.x - o2.x`) — they can overflow.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Chapter 4: Classes and Interfaces
|
|
241
|
+
|
|
242
|
+
### Item 15: Minimize the accessibility of classes and members
|
|
243
|
+
|
|
244
|
+
Make each class or member as inaccessible as possible. Top-level classes: package-private or public.
|
|
245
|
+
Members: private → package-private → protected → public (use the most restrictive that works).
|
|
246
|
+
Instance fields should never be public. Public static final fields are OK only for immutable objects.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
### Item 16: In public classes, use accessor methods, not public fields
|
|
251
|
+
|
|
252
|
+
Don't expose fields directly — use getters (and setters only if mutable).
|
|
253
|
+
Exception: package-private or private nested classes can expose fields.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### Item 17: Minimize mutability
|
|
258
|
+
|
|
259
|
+
Immutable classes are simpler, thread-safe, and can be shared freely. Rules:
|
|
260
|
+
1. Don't provide mutators
|
|
261
|
+
2. Ensure class can't be extended (make it final or use static factories with private constructor)
|
|
262
|
+
3. Make all fields final
|
|
263
|
+
4. Make all fields private
|
|
264
|
+
5. Ensure exclusive access to mutable components (defensive copies)
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Item 18: Favor composition over inheritance
|
|
269
|
+
|
|
270
|
+
Inheritance across package boundaries is fragile. Use the decorator pattern:
|
|
271
|
+
a forwarding class that wraps the existing class and delegates all method calls.
|
|
272
|
+
|
|
273
|
+
**Anti-pattern**: `class InstrumentedHashSet<E> extends HashSet<E>` — breaks if `HashSet.addAll` calls `add`.
|
|
274
|
+
|
|
275
|
+
**Correct**: `class InstrumentedSet<E> extends ForwardingSet<E>` wrapping any `Set<E>`.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### Item 19: Design and document for inheritance or else prohibit it
|
|
280
|
+
|
|
281
|
+
Classes designed for subclassing must document self-use of overridable methods.
|
|
282
|
+
If you don't design for inheritance, make the class final or make constructors private with static factories.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### Item 20: Prefer interfaces to abstract classes
|
|
287
|
+
|
|
288
|
+
Interfaces enable mixins, non-hierarchical type frameworks, and default methods.
|
|
289
|
+
Use skeletal implementation classes (e.g., `AbstractList`) as optional companions.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
### Item 21: Design interfaces for posterity
|
|
294
|
+
|
|
295
|
+
Default methods can break existing implementations. Think carefully before adding
|
|
296
|
+
default methods to existing interfaces — they may violate invariants of existing implementations.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### Item 22: Use interfaces only to define types
|
|
301
|
+
|
|
302
|
+
Don't use constant interfaces (interfaces with only `static final` fields).
|
|
303
|
+
Use enum types or utility classes for constants instead.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### Item 23: Prefer class hierarchies to tagged classes
|
|
308
|
+
|
|
309
|
+
Tagged classes (a class with a `type` field and switch statements) are verbose, error-prone,
|
|
310
|
+
and inefficient. Refactor into a class hierarchy with an abstract root class.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
### Item 24: Favor static member classes over nonstatic
|
|
315
|
+
|
|
316
|
+
Four kinds of nested classes: static member, nonstatic member, anonymous, local.
|
|
317
|
+
If a member class doesn't need a reference to the enclosing instance, make it static.
|
|
318
|
+
Non-static member classes retain a hidden reference to the enclosing instance (memory leak risk).
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### Item 25: Limit source files to a single top-level class
|
|
323
|
+
|
|
324
|
+
Never put multiple top-level classes in a single source file. Use static member classes
|
|
325
|
+
if the classes are closely related.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Chapter 5: Generics
|
|
330
|
+
|
|
331
|
+
### Item 26: Don't use raw types
|
|
332
|
+
|
|
333
|
+
Raw types lose type safety. Use `List<Object>` if you want a list that can hold any object,
|
|
334
|
+
`List<?>` if you want a list of some unknown type.
|
|
335
|
+
|
|
336
|
+
**Anti-pattern**: `List list = new ArrayList();`
|
|
337
|
+
**Correct**: `List<String> list = new ArrayList<>();`
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### Item 27: Eliminate unchecked warnings
|
|
342
|
+
|
|
343
|
+
Every unchecked warning represents a potential `ClassCastException` at runtime.
|
|
344
|
+
Eliminate every warning you can. If you can prove the code is typesafe but can't
|
|
345
|
+
eliminate the warning, suppress it with `@SuppressWarnings("unchecked")` on the
|
|
346
|
+
smallest possible scope, and add a comment explaining why it's safe.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### Item 28: Prefer lists to arrays
|
|
351
|
+
|
|
352
|
+
Arrays are covariant and reified; generics are invariant and erased. These differences
|
|
353
|
+
make arrays and generics poor mixmates. Prefer `List<E>` to `E[]`.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### Item 29: Favor generic types
|
|
358
|
+
|
|
359
|
+
Generify your classes. It's not much harder than using raw types and provides compile-time safety.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
### Item 30: Favor generic methods
|
|
364
|
+
|
|
365
|
+
Generic methods are especially useful for static utility methods.
|
|
366
|
+
Use type inference: `Set<String> union = union(s1, s2);`
|
|
367
|
+
|
|
368
|
+
**Recursive type bounds** for mutual comparability:
|
|
369
|
+
```java
|
|
370
|
+
public static <E extends Comparable<E>> E max(Collection<E> c)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
### Item 31: Use bounded wildcards to increase API flexibility
|
|
376
|
+
|
|
377
|
+
PECS: Producer-Extends, Consumer-Super.
|
|
378
|
+
- If a parameter is a **producer** of `T`, use `<? extends T>`
|
|
379
|
+
- If a parameter is a **consumer** of `T`, use `<? super T>`
|
|
380
|
+
- Do not use wildcards on return types
|
|
381
|
+
|
|
382
|
+
```java
|
|
383
|
+
public void pushAll(Iterable<? extends E> src) { ... } // src produces E
|
|
384
|
+
public void popAll(Collection<? super E> dst) { ... } // dst consumes E
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
### Item 32: Combine generics and varargs judiciously
|
|
390
|
+
|
|
391
|
+
Heap pollution can occur with generic varargs parameters. Use `@SafeVarargs`
|
|
392
|
+
on every method with a varargs parameter of a generic or parameterized type,
|
|
393
|
+
provided the method is truly safe (doesn't store into the varargs array or
|
|
394
|
+
expose it to untrusted code).
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### Item 33: Consider typesafe heterogeneous containers
|
|
399
|
+
|
|
400
|
+
Use `Class<T>` as a key to store and retrieve values of different types safely.
|
|
401
|
+
Pattern: `Map<Class<?>, Object>` with runtime type checking on put/get.
|
|
402
|
+
|
|
403
|
+
```java
|
|
404
|
+
public <T> void putFavorite(Class<T> type, T instance);
|
|
405
|
+
public <T> T getFavorite(Class<T> type);
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Chapter 6: Enums and Annotations
|
|
411
|
+
|
|
412
|
+
### Item 34: Use enums instead of int constants
|
|
413
|
+
|
|
414
|
+
Enums provide compile-time type safety, namespaces, and can have behavior.
|
|
415
|
+
Use constant-specific method implementations for behavior that varies by constant.
|
|
416
|
+
Use the strategy enum pattern for shared behaviors.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
### Item 35: Use instance fields instead of ordinals
|
|
421
|
+
|
|
422
|
+
Never derive a value from `ordinal()`. Store the value in an instance field.
|
|
423
|
+
|
|
424
|
+
**Anti-pattern**: `public int numberOfMusicians() { return ordinal() + 1; }`
|
|
425
|
+
**Correct**: Store the count as a constructor parameter.
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### Item 36: Use EnumSet instead of bit fields
|
|
430
|
+
|
|
431
|
+
`EnumSet` provides the performance of bit fields with the readability and type safety of enums.
|
|
432
|
+
|
|
433
|
+
```java
|
|
434
|
+
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
### Item 37: Use EnumMap instead of ordinal indexing
|
|
440
|
+
|
|
441
|
+
Use `EnumMap` instead of `array[enum.ordinal()]` for enum-keyed maps. Also applicable
|
|
442
|
+
for multi-dimensional mappings: use nested `EnumMap<..., EnumMap<..., V>>`.
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
### Item 38: Emulate extensible enums with interfaces
|
|
447
|
+
|
|
448
|
+
Enums can't extend other enums, but they can implement interfaces.
|
|
449
|
+
Use this for extensible operation codes (opcode pattern).
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
### Item 39: Prefer annotations to naming patterns
|
|
454
|
+
|
|
455
|
+
Annotations (like `@Test`) are superior to naming conventions (like `testXxx`).
|
|
456
|
+
Use meta-annotations to create custom annotations.
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
### Item 40: Consistently use the Override annotation
|
|
461
|
+
|
|
462
|
+
Use `@Override` on every method declaration intended to override a superclass or
|
|
463
|
+
interface method. The compiler will catch errors if the method doesn't actually override.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### Item 41: Use marker interfaces to define types
|
|
468
|
+
|
|
469
|
+
Marker interfaces (like `Serializable`) define a type that instances of marked classes
|
|
470
|
+
have. Use them when you need compile-time type checking. Use marker annotations when
|
|
471
|
+
you don't need the type.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Chapter 7: Lambdas and Streams
|
|
476
|
+
|
|
477
|
+
### Item 42: Prefer lambdas to anonymous classes
|
|
478
|
+
|
|
479
|
+
Lambdas are more concise than anonymous classes for functional interface implementations.
|
|
480
|
+
Keep lambdas short (1-3 lines). If a lambda is long, extract it to a method.
|
|
481
|
+
Lambdas lack names and documentation — if a computation isn't self-explanatory, don't use one.
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### Item 43: Prefer method references to lambdas
|
|
486
|
+
|
|
487
|
+
Method references are more concise and clearer when they don't need parameter renaming.
|
|
488
|
+
|
|
489
|
+
| Method Ref Type | Example | Lambda Equivalent |
|
|
490
|
+
|----------------|---------|-------------------|
|
|
491
|
+
| Static | `Integer::parseInt` | `str -> Integer.parseInt(str)` |
|
|
492
|
+
| Bound | `Instant.now()::isAfter` | `t -> Instant.now().isAfter(t)` |
|
|
493
|
+
| Unbound | `String::toLowerCase` | `str -> str.toLowerCase()` |
|
|
494
|
+
| Constructor | `TreeMap<K,V>::new` | `() -> new TreeMap<K,V>()` |
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
### Item 44: Favor the use of standard functional interfaces
|
|
499
|
+
|
|
500
|
+
Use the 43 interfaces in `java.util.function` before creating your own.
|
|
501
|
+
Six basic ones: `UnaryOperator<T>`, `BinaryOperator<T>`, `Predicate<T>`,
|
|
502
|
+
`Function<T,R>`, `Supplier<T>`, `Consumer<T>`.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
### Item 45: Use streams judiciously
|
|
507
|
+
|
|
508
|
+
Don't overuse streams. Overusing streams makes code hard to read and maintain.
|
|
509
|
+
Good for: transforming sequences, filtering, combining, accumulating into collections,
|
|
510
|
+
searching. Bad for: accessing corresponding elements from multiple stages simultaneously,
|
|
511
|
+
modifying local variables from enclosing scope.
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
### Item 46: Prefer side-effect-free functions in streams
|
|
516
|
+
|
|
517
|
+
The most important part of the streams paradigm is to structure your computation as
|
|
518
|
+
a sequence of transformations where each stage's result is as close as possible to a
|
|
519
|
+
pure function. The `forEach` operation should only be used to report the result of a
|
|
520
|
+
stream computation, not to perform computation.
|
|
521
|
+
|
|
522
|
+
**Key collectors**: `toList()`, `toSet()`, `toMap()`, `groupingBy()`, `joining()`.
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
### Item 47: Prefer Collection to Stream as a return type
|
|
527
|
+
|
|
528
|
+
`Collection` is a subtype of both `Iterable` and `Stream`, making it the best return
|
|
529
|
+
type for public APIs. If the values aren't stored in memory, consider returning a custom
|
|
530
|
+
collection backed by computation.
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
### Item 48: Use caution when making streams parallel
|
|
535
|
+
|
|
536
|
+
Parallelizing a stream is easy to do but can cause incorrect results or poor performance.
|
|
537
|
+
Performance gains are best with `ArrayList`, `HashMap`, `HashSet`, `ConcurrentHashMap`,
|
|
538
|
+
arrays, `int` ranges, and `long` ranges — data structures that can be cheaply split.
|
|
539
|
+
Avoid parallelizing pipelines backed by `Stream.iterate` or `limit`.
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## Chapter 8: Methods
|
|
544
|
+
|
|
545
|
+
### Item 49: Check parameters for validity
|
|
546
|
+
|
|
547
|
+
Validate parameters at the start of methods. Use `Objects.requireNonNull` for null checks.
|
|
548
|
+
Use `assert` for non-public methods. Document restrictions with `@throws` Javadoc.
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
### Item 50: Make defensive copies when needed
|
|
553
|
+
|
|
554
|
+
When receiving mutable objects from clients, make defensive copies in the constructor
|
|
555
|
+
(before validation). When returning mutable internal state, return copies.
|
|
556
|
+
|
|
557
|
+
**Critical**: Copy first, validate the copy — prevents TOCTOU attacks.
|
|
558
|
+
|
|
559
|
+
```java
|
|
560
|
+
public Period(Date start, Date end) {
|
|
561
|
+
this.start = new Date(start.getTime()); // Defensive copy
|
|
562
|
+
this.end = new Date(end.getTime());
|
|
563
|
+
if (this.start.compareTo(this.end) > 0) // Validate copy
|
|
564
|
+
throw new IllegalArgumentException();
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
### Item 51: Design method signatures carefully
|
|
571
|
+
|
|
572
|
+
- Choose method names carefully (consistent, understandable)
|
|
573
|
+
- Don't go overboard with convenience methods
|
|
574
|
+
- Avoid long parameter lists (max 4) — use helper classes, Builder, or break into multiple methods
|
|
575
|
+
- Prefer interfaces over classes for parameter types
|
|
576
|
+
- Prefer two-element enum types to boolean parameters
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
### Item 52: Use overloading judiciously
|
|
581
|
+
|
|
582
|
+
Overloading selection is static (compile-time), not dynamic (runtime). Avoid overloading
|
|
583
|
+
methods with the same number of parameters. Use different method names instead.
|
|
584
|
+
|
|
585
|
+
**Dangerous**: `List.remove(int)` vs `List.remove(Object)` — autoboxing creates confusion.
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
### Item 53: Use varargs judiciously
|
|
590
|
+
|
|
591
|
+
Require at least one argument pattern:
|
|
592
|
+
```java
|
|
593
|
+
static int min(int firstArg, int... remainingArgs) { ... }
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
Performance concern: varargs allocates an array. For performance-critical methods,
|
|
597
|
+
provide overloads for 0-3 args plus varargs fallback.
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
### Item 54: Return empty collections or arrays, not nulls
|
|
602
|
+
|
|
603
|
+
Never return null from a collection-returning method. Use `Collections.emptyList()`,
|
|
604
|
+
`Collections.emptySet()`, `Collections.emptyMap()`, or empty arrays.
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
### Item 55: Return optionals judiciously
|
|
609
|
+
|
|
610
|
+
Use `Optional<T>` for methods that might not return a result. Never return `null`
|
|
611
|
+
from an Optional-returning method. Never use Optional for collection return types
|
|
612
|
+
(return empty collection instead). Don't use Optional in fields, parameters, or map keys/values.
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
### Item 56: Write doc comments for all exposed API elements
|
|
617
|
+
|
|
618
|
+
Document every exported class, interface, method, constructor, and field.
|
|
619
|
+
The doc comment should describe the contract: what the method does (not how),
|
|
620
|
+
preconditions, postconditions, side effects, and thread safety.
|
|
621
|
+
|
|
622
|
+
Use `@param`, `@return`, `@throws`, `{@code}`, `{@literal}`, `{@index}`, `@implSpec`.
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## Chapter 9: General Programming
|
|
627
|
+
|
|
628
|
+
### Item 57: Minimize the scope of local variables
|
|
629
|
+
|
|
630
|
+
Declare variables where they are first used. Prefer for-loop to while-loop when
|
|
631
|
+
the loop variable isn't needed afterward. Keep methods small and focused.
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
### Item 58: Prefer for-each loops to traditional for loops
|
|
636
|
+
|
|
637
|
+
Use enhanced for-each wherever possible. Three situations where you can't:
|
|
638
|
+
destructive filtering, transforming, and parallel iteration.
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
### Item 59: Know and use the libraries
|
|
643
|
+
|
|
644
|
+
Don't reinvent the wheel. Use `java.util`, `java.util.concurrent`, `java.util.stream`,
|
|
645
|
+
`java.time`, etc. Example: `ThreadLocalRandom.current().nextInt(bound)` instead of
|
|
646
|
+
hand-rolled random number generation.
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
### Item 60: Avoid float and double if exact answers are required
|
|
651
|
+
|
|
652
|
+
Use `BigDecimal`, `int`, or `long` for monetary calculations. `float` and `double`
|
|
653
|
+
are designed for scientific computation, not exact decimal values.
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
### Item 61: Prefer primitive types to boxed primitives
|
|
658
|
+
|
|
659
|
+
Prefer `int` over `Integer`, `long` over `Long`. Unintentional autoboxing causes
|
|
660
|
+
performance issues. Applying `==` to boxed primitives is almost always wrong.
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
### Item 62: Avoid strings where other types are more appropriate
|
|
665
|
+
|
|
666
|
+
Don't use strings as substitutes for enums, aggregates, or capabilities.
|
|
667
|
+
Use proper types: enums for enumerated values, classes for aggregates, keys for capabilities.
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
### Item 63: Beware the performance of string concatenation
|
|
672
|
+
|
|
673
|
+
Use `StringBuilder` when concatenating many strings in a loop.
|
|
674
|
+
The `+` operator is fine for a fixed number of strings.
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
### Item 64: Refer to objects by their interfaces
|
|
679
|
+
|
|
680
|
+
If appropriate interface types exist, parameters, return values, variables, and fields
|
|
681
|
+
should all be declared as interface types.
|
|
682
|
+
|
|
683
|
+
```java
|
|
684
|
+
Set<Son> sonSet = new LinkedHashSet<>(); // Good
|
|
685
|
+
LinkedHashSet<Son> sonSet = new LinkedHashSet<>(); // Bad
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
### Item 65: Prefer interfaces to reflection
|
|
691
|
+
|
|
692
|
+
Reflection is powerful but has many disadvantages: no compile-time checking, verbose code,
|
|
693
|
+
poor performance. Use reflection only to instantiate classes, then access via interfaces.
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
### Item 66: Use native methods judiciously
|
|
698
|
+
|
|
699
|
+
Rarely need JNI for performance anymore. Use only for accessing platform-specific
|
|
700
|
+
facilities not available in Java.
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
### Item 67: Optimize judiciously
|
|
705
|
+
|
|
706
|
+
Don't optimize prematurely. Write good programs first, then profile. Avoid architectural
|
|
707
|
+
decisions that limit performance (like making a public API return mutable internal state
|
|
708
|
+
requiring defensive copies on every call).
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
### Item 68: Adhere to generally accepted naming conventions
|
|
713
|
+
|
|
714
|
+
Follow Java naming conventions:
|
|
715
|
+
- Packages: `com.google.common.collect`
|
|
716
|
+
- Classes/Interfaces: `BigDecimal`, `Comparator`
|
|
717
|
+
- Methods: `ensureCapacity`, `getCrc`
|
|
718
|
+
- Constants: `MIN_VALUE`, `NEGATIVE_INFINITY`
|
|
719
|
+
- Type parameters: `T`, `E`, `K`, `V`, `X`, `R`, `T1`, `T2`
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
## Chapter 10: Exceptions
|
|
724
|
+
|
|
725
|
+
### Item 69: Use exceptions only for exceptional conditions
|
|
726
|
+
|
|
727
|
+
Never use exceptions for ordinary control flow. A well-designed API must not force
|
|
728
|
+
its clients to use exceptions for ordinary control flow (provide state-testing methods
|
|
729
|
+
or Optional-returning methods).
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
### Item 70: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
|
|
734
|
+
|
|
735
|
+
Checked exceptions: caller can reasonably recover.
|
|
736
|
+
Runtime exceptions: programming errors (precondition violations).
|
|
737
|
+
Errors: reserved for JVM. Don't subclass `Error`.
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
### Item 71: Avoid unnecessary use of checked exceptions
|
|
742
|
+
|
|
743
|
+
If the caller can't recover, use unchecked. If there's only one checked exception on
|
|
744
|
+
a method and it's the sole reason for the `throws` clause, consider returning `Optional`
|
|
745
|
+
instead or splitting the method.
|
|
746
|
+
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
### Item 72: Favor the use of standard exceptions
|
|
750
|
+
|
|
751
|
+
Common reusable exceptions:
|
|
752
|
+
- `IllegalArgumentException` — non-null parameter value is inappropriate
|
|
753
|
+
- `IllegalStateException` — object state is inappropriate for invocation
|
|
754
|
+
- `NullPointerException` — parameter is null where prohibited
|
|
755
|
+
- `IndexOutOfBoundsException` — index parameter out of range
|
|
756
|
+
- `UnsupportedOperationException` — object doesn't support method
|
|
757
|
+
- `ConcurrentModificationException` — concurrent modification detected
|
|
758
|
+
- `ArithmeticException` — arithmetic error
|
|
759
|
+
|
|
760
|
+
---
|
|
761
|
+
|
|
762
|
+
### Item 73: Throw exceptions appropriate to the abstraction
|
|
763
|
+
|
|
764
|
+
Higher layers should catch lower-level exceptions and throw exceptions appropriate to
|
|
765
|
+
their abstraction (exception translation). Use exception chaining to preserve the cause.
|
|
766
|
+
|
|
767
|
+
```java
|
|
768
|
+
try {
|
|
769
|
+
// Lower-level abstraction
|
|
770
|
+
} catch (LowerLevelException e) {
|
|
771
|
+
throw new HigherLevelException(e); // Exception chaining
|
|
772
|
+
}
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
777
|
+
### Item 74: Document all exceptions thrown by each method
|
|
778
|
+
|
|
779
|
+
Document every exception with `@throws` Javadoc. Declare checked exceptions individually.
|
|
780
|
+
Don't declare that a method `throws Exception` or `throws Throwable`.
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
### Item 75: Include failure-capture information in detail messages
|
|
785
|
+
|
|
786
|
+
Exception detail messages should include the values of all parameters and fields that
|
|
787
|
+
contributed to the exception. Don't include passwords or encryption keys.
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
### Item 76: Strive for failure atomicity
|
|
792
|
+
|
|
793
|
+
A failed method invocation should leave the object in the state it was in prior to
|
|
794
|
+
the invocation. Approaches: immutable objects, parameter validation before operation,
|
|
795
|
+
temporary copy, recovery code.
|
|
796
|
+
|
|
797
|
+
---
|
|
798
|
+
|
|
799
|
+
### Item 77: Don't ignore exceptions
|
|
800
|
+
|
|
801
|
+
An empty catch block defeats the purpose of exceptions. If you choose to ignore,
|
|
802
|
+
document why and name the variable `ignored`.
|
|
803
|
+
|
|
804
|
+
```java
|
|
805
|
+
try { ... }
|
|
806
|
+
catch (SomeException ignored) {
|
|
807
|
+
// Safe to ignore because [reason]
|
|
808
|
+
}
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
## Chapter 11: Concurrency
|
|
814
|
+
|
|
815
|
+
### Item 78: Synchronize access to shared mutable data
|
|
816
|
+
|
|
817
|
+
Synchronization is required for reliable communication between threads, not just mutual
|
|
818
|
+
exclusion. Use `volatile` for simple communication (e.g., stop flags). Use `synchronized`
|
|
819
|
+
or `java.util.concurrent.atomic` for compound actions.
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
### Item 79: Avoid excessive synchronization
|
|
824
|
+
|
|
825
|
+
Don't call alien methods from within synchronized regions (risk of deadlock or data corruption).
|
|
826
|
+
Do as little work as possible inside synchronized regions. Prefer `CopyOnWriteArrayList`
|
|
827
|
+
for observable lists with rare modifications.
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
### Item 80: Prefer executors, tasks, and streams to threads
|
|
832
|
+
|
|
833
|
+
Use `ExecutorService` instead of managing threads directly. Use `Executors.newCachedThreadPool`
|
|
834
|
+
for lightly loaded servers, `Executors.newFixedThreadPool` for heavily loaded servers.
|
|
835
|
+
Use `ForkJoinPool` for compute-intensive parallel tasks.
|
|
836
|
+
|
|
837
|
+
---
|
|
838
|
+
|
|
839
|
+
### Item 81: Prefer concurrency utilities to wait and notify
|
|
840
|
+
|
|
841
|
+
Use `ConcurrentHashMap`, `BlockingQueue`, `CountDownLatch`, `Semaphore`, and `Phaser`
|
|
842
|
+
instead of `wait`/`notify`. Use `ConcurrentHashMap.computeIfAbsent` for thread-safe lazy init.
|
|
843
|
+
Always use the wait loop idiom if you must use `wait`:
|
|
844
|
+
|
|
845
|
+
```java
|
|
846
|
+
synchronized (obj) {
|
|
847
|
+
while (!condition) obj.wait();
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
### Item 82: Document thread safety
|
|
854
|
+
|
|
855
|
+
Document the thread safety level of every class:
|
|
856
|
+
- **Immutable** — Instances are constant (`String`, `Long`, `BigInteger`)
|
|
857
|
+
- **Unconditionally thread-safe** — Mutable but with internal synchronization (`AtomicLong`, `ConcurrentHashMap`)
|
|
858
|
+
- **Conditionally thread-safe** — Some methods require external synchronization (`Collections.synchronized` wrappers)
|
|
859
|
+
- **Not thread-safe** — Must surround each method invocation with external sync (`ArrayList`, `HashMap`)
|
|
860
|
+
- **Thread-hostile** — Unsafe even with external sync (rare)
|
|
861
|
+
|
|
862
|
+
Use `@ThreadSafe`, `@NotThreadSafe`, `@Immutable` annotations (JSR 305).
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
### Item 83: Use lazy initialization judiciously
|
|
867
|
+
|
|
868
|
+
Most fields should be initialized normally (eagerly). Use lazy init only if needed
|
|
869
|
+
for performance or to break circular dependencies.
|
|
870
|
+
|
|
871
|
+
- **For instance fields**: double-check idiom
|
|
872
|
+
- **For static fields**: lazy initialization holder class idiom
|
|
873
|
+
- **For fields that can tolerate repeated init**: single-check idiom
|
|
874
|
+
|
|
875
|
+
```java
|
|
876
|
+
// Lazy initialization holder class idiom for static fields
|
|
877
|
+
private static class FieldHolder {
|
|
878
|
+
static final FieldType field = computeFieldValue();
|
|
879
|
+
}
|
|
880
|
+
private static FieldType getField() { return FieldHolder.field; }
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
### Item 84: Don't depend on the thread scheduler
|
|
886
|
+
|
|
887
|
+
Programs that rely on thread scheduling for correctness or performance are non-portable.
|
|
888
|
+
Don't use `Thread.yield`. Don't use thread priorities. If threads aren't doing useful work,
|
|
889
|
+
restructure the application so they don't run.
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## Chapter 12: Serialization
|
|
894
|
+
|
|
895
|
+
### Item 85: Prefer alternatives to Java serialization
|
|
896
|
+
|
|
897
|
+
Java serialization is dangerous — it enables remote code execution attacks via gadget chains.
|
|
898
|
+
Prefer cross-platform structured-data representations: JSON or protobuf.
|
|
899
|
+
Never deserialize untrusted data. If you must use serialization, use object deserialization
|
|
900
|
+
filtering (`java.io.ObjectInputFilter`).
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
### Item 86: Implement Serializable with great caution
|
|
905
|
+
|
|
906
|
+
Implementing `Serializable` decreases the flexibility to change a class's implementation,
|
|
907
|
+
increases the likelihood of bugs and security holes, and increases the testing burden.
|
|
908
|
+
Classes designed for inheritance should rarely implement `Serializable`.
|
|
909
|
+
|
|
910
|
+
---
|
|
911
|
+
|
|
912
|
+
### Item 87: Consider using a custom serialized form
|
|
913
|
+
|
|
914
|
+
Don't accept the default serialized form without considering whether it's appropriate.
|
|
915
|
+
The default form is reasonable only if the physical representation is identical to the
|
|
916
|
+
logical content. Otherwise, write `writeObject`/`readObject` methods.
|
|
917
|
+
|
|
918
|
+
Mark fields that are derivable from other state as `transient`.
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
|
|
922
|
+
### Item 88: Write readObject methods defensively
|
|
923
|
+
|
|
924
|
+
`readObject` is effectively a public constructor — it must validate parameters and make
|
|
925
|
+
defensive copies of mutable components, just like any other constructor.
|
|
926
|
+
|
|
927
|
+
---
|
|
928
|
+
|
|
929
|
+
### Item 89: For instance control, prefer enum types to readResolve
|
|
930
|
+
|
|
931
|
+
If a singleton class implements `Serializable`, add a `readResolve` method or,
|
|
932
|
+
better yet, use a single-element enum. With `readResolve`, all instance fields
|
|
933
|
+
with object reference types must be declared `transient`.
|
|
934
|
+
|
|
935
|
+
---
|
|
936
|
+
|
|
937
|
+
### Item 90: Consider serialization proxies instead of serialized instances
|
|
938
|
+
|
|
939
|
+
The serialization proxy pattern: write a private static nested class that represents
|
|
940
|
+
the logical state, implement `writeReplace` and `readResolve`. This is the most robust
|
|
941
|
+
approach when you must implement `Serializable`.
|
|
942
|
+
|
|
943
|
+
```java
|
|
944
|
+
private static class SerializationProxy implements Serializable {
|
|
945
|
+
private final Date start;
|
|
946
|
+
private final Date end;
|
|
947
|
+
SerializationProxy(Period p) {
|
|
948
|
+
this.start = p.start;
|
|
949
|
+
this.end = p.end;
|
|
950
|
+
}
|
|
951
|
+
private Object readResolve() {
|
|
952
|
+
return new Period(start, end); // Uses public constructor
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
```
|