## Chapter 5. Generics(泛型)
### Item 32: Combine generics and varargs judiciously(明智地合用泛型和可變參數)
Varargs methods (Item 53) and generics were both added to the platform in Java 5, so you might expect them to interact gracefully; sadly, they do not. The purpose of varargs is to allow clients to pass a variable number of arguments to a method, but it is a leaky abstraction: when you invoke a varargs method, an array is created to hold the varargs parameters; that array, which should be an implementation detail, is visible. As a consequence, you get confusing compiler warnings when varargs parameters have generic or parameterized types.
可變參數方法([Item-53](/Chapter-8/Chapter-8-Item-53-Use-varargs-judiciously.md))和泛型都是在 Java 5 中添加的,因此你可能認為它們能夠優雅地交互;可悲的是,他們并不能。可變參數的目的是允許客戶端向方法傳遞可變數量的參數,但這是一個抽象泄漏:當你調用可變參數方法時,將創建一個數組來保存參數;該數組本應是實現細節,卻是可見的。因此,當可變參數具有泛型或參數化類型時,會出現令人困惑的編譯器警告。
**譯注:有關「抽象泄漏」(Leaky Abstractions)的概念可參考 [奇舞精選 2021-07-06 的文章](https://mp.weixin.qq.com/s/KneomYX_7yQ78RzAmvIoHg)**
Recall from Item 28 that a non-reifiable type is one whose runtime representation has less information than its compile-time representation, and that nearly all generic and parameterized types are non-reifiable. If a method declares its varargs parameter to be of a non-reifiable type, the compiler generates a warning on the declaration. If the method is invoked on varargs parameters whose inferred type is non-reifiable, the compiler generates a warning on the invocation too. The warnings look something like this:
回想一下 [Item-28](/Chapter-5/Chapter-5-Item-28-Prefer-lists-to-arrays.md),非具體化類型是指其運行時表示的信息少于其編譯時表示的信息,并且幾乎所有泛型和參數化類型都是不可具體化的。如果方法聲明其可變參數為不可具體化類型,編譯器將在聲明上生成警告。如果方法是在其推斷類型不可具體化的可變參數上調用的,編譯器也會在調用時生成警告。生成的警告就像這樣:
```
warning: [unchecked] Possible heap pollution from parameterized vararg type List<String>
```
Heap pollution occurs when a variable of a parameterized type refers to an object that is not of that type [JLS, 4.12.2]. It can cause the compiler’s automatically generated casts to fail, violating the fundamental guarantee of the generic type system.
當參數化類型的變量引用不屬于該類型的對象時,就會發生堆污染[JLS, 4.12.2]。它會導致編譯器自動生成的強制類型轉換失敗,違反泛型類型系統的基本保證。
For example, consider this method, which is a thinly disguised(偽裝的) variant of the code fragment on page 127:
例如,考慮這個方法,它摘自 127 頁([Item-26](/Chapter-5/Chapter-5-Item-26-Do-not-use-raw-types.md))的代碼片段,但做了些修改:
```
// Mixing generics and varargs can violate type safety!
// 泛型和可變參數混合使用可能違反類型安全原則!
static void dangerous(List<String>... stringLists) {
List<Integer> intList = List.of(42);
Object[] objects = stringLists;
objects[0] = intList; // Heap pollution
String s = stringLists[0].get(0); // ClassCastException
}
```
This method has no visible casts yet throws a ClassCastException when invoked with one or more arguments. Its last line has an invisible cast that is generated by the compiler. This cast fails, demonstrating that type safety has been compromised, and **it is unsafe to store a value in a generic varargs array parameter.**
此方法沒有顯式的強制類型轉換,但在使用一個或多個參數調用時拋出 ClassCastException。它的最后一行有一個由編譯器生成的隱式強制轉換。此轉換失敗,表明類型安全性受到了影響,并且**在泛型可變參數數組中存儲值是不安全的。**
This example raises an interesting question: Why is it even legal to declare a method with a generic varargs parameter, when it is illegal to create a generic array explicitly? In other words, why does the method shown previously generate only a warning, while the code fragment on page 127 generates an error? The answer is that methods with varargs parameters of generic or parameterized types can be very useful in practice, so the language designers opted to live with this inconsistency. In fact, the Java libraries export several such methods, including `Arrays.asList(T... a)`, `Collections.addAll(Collection<? super T> c, T... elements)`, and `EnumSet.of(E first, E... rest)`. Unlike the dangerous method shown earlier, these library methods are typesafe.
這個例子提出了一個有趣的問題:為什么使用泛型可變參數聲明方法是合法的,而顯式創建泛型數組是非法的?換句話說,為什么前面顯示的方法只生成警告,而 127 頁上的代碼片段發生錯誤?答案是,帶有泛型或參數化類型的可變參數的方法在實際開發中非常有用,因此語言設計人員選擇忍受這種不一致性。事實上,Java 庫導出了幾個這樣的方法,包括 `Arrays.asList(T... a)`、`Collections.addAll(Collection<? super T> c, T... elements)` 以及 `EnumSet.of(E first, E... rest)`。它們與前面顯示的危險方法不同,這些庫方法是類型安全的。
Prior to Java 7, there was nothing the author of a method with a generic varargs parameter could do about the warnings at the call sites. This made these APIs unpleasant to use. Users had to put up with the warnings or, preferably, to eliminate them with @SuppressWarnings("unchecked") annotations at every call site (Item 27). This was tedious, harmed readability, and hid warnings that flagged real issues.
在 Java 7 之前,使用泛型可變參數的方法的作者對調用點上產生的警告無能為力。使得這些 API 難以使用。用戶必須忍受這些警告,或者在每個調用點([Item-27](/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md))使用 @SuppressWarnings("unchecked") 注釋消除這些警告。這種做法乏善可陳,既損害了可讀性,也忽略了標記實際問題的警告。
In Java 7, the SafeVarargs annotation was added to the platform, to allow the author of a method with a generic varargs parameter to suppress client warnings automatically. In essence, **the SafeVarargs annotation constitutes a promise by the author of a method that it is typesafe.** In exchange for this promise, the compiler agrees not to warn the users of the method that calls may be unsafe.
在 Java 7 中添加了 SafeVarargs 注釋,以允許使用泛型可變參數的方法的作者自動抑制客戶端警告。本質上,**SafeVarargs 注釋構成了方法作者的一個承諾,即該方法是類型安全的。** 作為這個承諾的交換條件,編譯器同意不對調用可能不安全的方法的用戶發出警告。
It is critical that you do not annotate a method with @SafeVarargs unless it actually is safe. So what does it take to ensure this? Recall that a generic array is created when the method is invoked, to hold the varargs parameters. If the method doesn’t store anything into the array (which would overwrite the parameters) and doesn’t allow a reference to the array to escape (which would enable untrusted code to access the array), then it’s safe. In other words, if the varargs parameter array is used only to transmit a variable number of arguments from the caller to the method—which is, after all, the purpose of varargs—then the method is safe.
關鍵問題是,使用 @SafeVarargs 注釋方法,該方法實際上應該是安全的。那么怎樣才能確保這一點呢?回想一下,在調用該方法時創建了一個泛型數組來保存可變參數。如果方法沒有將任何內容存儲到數組中(這會覆蓋參數),并且不允許對數組的引用進行轉義(這會使不受信任的代碼能夠訪問數組),那么它就是安全的。換句話說,如果可變參數數組僅用于將可變數量的參數從調用方傳輸到方法(畢竟這是可變參數的目的),那么該方法是安全的。
It is worth noting that you can violate type safety without ever storing anything in the varargs parameter array. Consider the following generic varargs method, which returns an array containing its parameters. At first glance, it may look like a handy little utility:
值得注意的是,在可變參數數組中不存儲任何東西就可能違反類型安全性。考慮下面的通用可變參數方法,它返回一個包含參數的數組。乍一看,它似乎是一個方便的小實用程序:
```
// UNSAFE - Exposes a reference to its generic parameter array!
static <T> T[] toArray(T... args) {
return args;
}
```
This method simply returns its varargs parameter array. The method may not look dangerous, but it is! The type of this array is determined by the compiletime types of the arguments passed in to the method, and the compiler may not have enough information to make an accurate determination. Because this method returns its varargs parameter array, it can propagate heap pollution up the call stack.
這個方法只是返回它的可變參數數組。這種方法看起來并不危險,但確實危險!這個數組的類型由傳遞給方法的參數的編譯時類型決定,編譯器可能沒有足夠的信息來做出準確的決定。因為這個方法返回它的可變參數數組,所以它可以將堆污染傳播到調用堆棧上。
To make this concrete, consider the following generic method, which takes three arguments of type T and returns an array containing two of the arguments, chosen at random:
為了使其具體化,請考慮下面的泛型方法,該方法接受三個類型為 T 的參數,并返回一個包含隨機選擇的兩個參數的數組:
```
static <T> T[] pickTwo(T a, T b, T c) {
switch(ThreadLocalRandom.current().nextInt(3)) {
case 0: return toArray(a, b);
case 1: return toArray(a, c);
case 2: return toArray(b, c);
}
throw new AssertionError(); // Can't get here
}
```
This method is not, in and of itself, dangerous and would not generate a warning except that it invokes the toArray method, which has a generic varargs parameter.
這個方法本身并不危險,并且不會生成警告,除非它調用 toArray 方法,該方法有一個通用的可變參數。
When compiling this method, the compiler generates code to create a varargs parameter array in which to pass two T instances to toArray. This code allocates an array of type Object[], which is the most specific type that is guaranteed to hold these instances, no matter what types of objects are passed to pickTwo at the call site. The toArray method simply returns this array to pickTwo, which in turn returns it to its caller, so pickTwo will always return an array of type Object[].
編譯此方法時,編譯器生成代碼來創建一個可變參數數組,在該數組中向 toArray 傳遞兩個 T 實例。這段代碼分配了 type Object[] 的一個數組,這是保證保存這些實例的最特定的類型,無論調用站點上傳遞給 pickTwo 的是什么類型的對象。toArray 方法只是將這個數組返回給 pickTwo,而 pickTwo 又將這個數組返回給它的調用者,所以 pickTwo 總是返回一個 Object[] 類型的數組。
Now consider this main method, which exercises pickTwo:
現在考慮這個主要方法,練習 pickTwo:
```
public static void main(String[] args) {
String[] attributes = pickTwo("Good", "Fast", "Cheap");
}
```
There is nothing at all wrong with this method, so it compiles without generating any warnings. But when you run it, it throws a ClassCastException, though it contains no visible casts. What you don’t see is that the compiler has generated a hidden cast to String[] on the value returned by pickTwo so that it can be stored in attributes. The cast fails, because Object[] is not a subtype of String[]. This failure is quite disconcerting because it is two levels removed from the method that actually causes the heap pollution (toArray), and the varargs parameter array is not modified after the actual parameters are stored in it.
這個方法沒有任何錯誤,因此它在編譯時不會生成任何警告。但是當你運行它時,它會拋出 ClassCastException,盡管它不包含可見的強制類型轉換。你沒有看到的是,編譯器在 pickTwo 返回的值上生成了一個隱藏的 String[] 轉換,這樣它就可以存儲在屬性中。轉換失敗,因為 Object[] 不是 String[] 的子類型。這個失敗非常令人不安,因為它是從方法中刪除了兩個導致堆污染的級別(toArray),并且可變參數數組在實際參數存儲在其中之后不會被修改。
This example is meant to drive home the point that **it is unsafe to give another method access to a generic varargs parameter array,** with two exceptions: it is safe to pass the array to another varargs method that is correctly annotated with @SafeVarargs, and it is safe to pass the array to a non-varargs method that merely computes some function of the contents of the array.
這個示例的目的是讓人明白,**讓另一個方法訪問泛型可變參數數組是不安全的**,只有兩個例外:將數組傳遞給另一個使用 @SafeVarargs 正確注釋的可變參數方法是安全的,將數組傳遞給僅計算數組內容的某個函數的非可變方法也是安全的。
Here is a typical example of a safe use of a generic varargs parameter. This method takes an arbitrary number of lists as arguments and returns a single list containing the elements of all of the input lists in sequence. Because the method is annotated with @SafeVarargs, it doesn’t generate any warnings, on the declaration or at its call sites:
下面是一個安全使用泛型可變參數的典型示例。該方法接受任意數量的列表作為參數,并返回一個包含所有輸入列表的元素的序列列表。因為該方法是用 @SafeVarargs 注釋的,所以它不會在聲明或調用點上生成任何警告:
```
// Safe method with a generic varargs parameter
@SafeVarargs
static <T> List<T> flatten(List<? extends T>... lists) {
List<T> result = new ArrayList<>();
for (List<? extends T> list : lists)
result.addAll(list);
return result;
}
```
The rule for deciding when to use the SafeVarargs annotation is simple: **Use @SafeVarargs on every method with a varargs parameter of a generic or parameterized type,** so its users won’t be burdened by needless and confusing compiler warnings. This implies that you should never write unsafe varargs methods like dangerous or toArray. Every time the compiler warns you of possible heap pollution from a generic varargs parameter in a method you control, check that the method is safe. As a reminder, a generic varargs methods is safe if:
決定何時使用 SafeVarargs 注釋的規則很簡單:**在每個帶有泛型或參數化類型的可變參數的方法上使用 @SafeVarargs**,這樣它的用戶就不會被不必要的和令人困惑的編譯器警告所困擾。這意味著你永遠不應該編寫像 dangerous 或 toArray 這樣不安全的可變參數方法。每當編譯器警告你控制的方法中的泛型可變參數可能造成堆污染時,請檢查該方法是否安全。提醒一下,一個通用的可變參數方法是安全的,如果:
1. it doesn’t store anything in the varargs parameter array, and
它沒有在可變參數數組中存儲任何東西,并且
2. it doesn’t make the array (or a clone) visible to untrusted code. If either of
these prohibitions is violated, fix it.
它不會讓數組(或者其副本)出現在不可信的代碼中。如果違反了這些禁令中的任何一條,就糾正它。
Note that the SafeVarargs annotation is legal only on methods that can’t be overridden, because it is impossible to guarantee that every possible overriding method will be safe. In Java 8, the annotation was legal only on static methods and final instance methods; in Java 9, it became legal on private instance methods as well.
請注意,SafeVarargs 注釋僅對不能覆蓋的方法合法,因為不可能保證所有可能覆蓋的方法都是安全的。在 Java 8 中,注釋僅對靜態方法和最終實例方法合法;在 Java 9 中,它在私有實例方法上也成為合法的。
An alternative to using the SafeVarargs annotation is to take the advice of Item 28 and replace the varargs parameter (which is an array in disguise) with a List parameter. Here’s how this approach looks when applied to our flatten method. Note that only the parameter declaration has changed:
使用 SafeVarargs 注釋的另一種選擇是接受 [Item-28](/Chapter-5/Chapter-5-Item-28-Prefer-lists-to-arrays.md) 的建議,并用 List 參數替換可變參數(它是一個偽裝的數組)。下面是將這種方法應用到我們的 flatten 方法時的效果。注意,只有參數聲明發生了更改:
```
// List as a typesafe alternative to a generic varargs parameter
static <T> List<T> flatten(List<List<? extends T>> lists) {
List<T> result = new ArrayList<>();
for (List<? extends T> list : lists)
result.addAll(list);
return result;
}
```
This method can then be used in conjunction with the static factory method List.of to allow for a variable number of arguments. Note that this approach relies on the fact that the List.of declaration is annotated with @SafeVarargs:
然后可以將此方法與靜態工廠方法 List.of 一起使用,以允許可變數量的參數。注意,這種方法依賴于 List.of 聲明是用 @SafeVarargs 注釋的:
```
audience = flatten(List.of(friends, romans, countrymen));
```
The advantage of this approach is that the compiler can prove that the method is typesafe. You don’t have to vouch for its safety with a SafeVarargs annotation, and you don’t have worry that you might have erred in determining that it was safe. The main disadvantage is that the client code is a bit more verbose and may be a bit slower.
這種方法的優點是編譯器可以證明該方法是類型安全的。你不必使用 SafeVarargs 注釋來保證它的安全性,也不必擔心在確定它的安全性時可能出錯。主要的缺點是客戶端代碼比較冗長,可能會比較慢。
This trick can also be used in situations where it is impossible to write a safe varargs method, as is the case with the toArray method on page 147. Its List analogue is the List.of method, so we don’t even have to write it; the Java libraries authors have done the work for us. The pickTwo method then becomes this:
這種技巧也可用于無法編寫安全的可變參數方法的情況,如第 147 頁中的 toArray 方法。它的列表類似于 List.of 方法,我們甚至不用寫;Java 庫的作者為我們做了這些工作。pickTwo 方法變成這樣:
```
static <T> List<T> pickTwo(T a, T b, T c) {
switch(rnd.nextInt(3)) {
case 0: return List.of(a, b);
case 1: return List.of(a, c);
case 2: return List.of(b, c);
}
throw new AssertionError();
}
```
and the main method becomes this:
main 方法是這樣的:
```
public static void main(String[] args) {
List<String> attributes = pickTwo("Good", "Fast", "Cheap");
}
```
The resulting code is typesafe because it uses only generics, and not arrays.
生成的代碼是類型安全的,因為它只使用泛型,而不使用數組。
In summary, varargs and generics do not interact well because the varargs facility is a leaky abstraction built atop arrays, and arrays have different type rules from generics. Though generic varargs parameters are not typesafe, they are legal. If you choose to write a method with a generic (or parameterized) varargs parameter, first ensure that the method is typesafe, and then annotate it with @SafeVarargs so it is not unpleasant to use.
總之,可變參數方法和泛型不能很好地交互,因為可變參數工具是構建在數組之上的漏洞抽象,并且數組具有與泛型不同的類型規則。雖然泛型可變參數不是類型安全的,但它們是合法的。如果選擇使用泛型(或參數化)可變參數編寫方法,首先要確保該方法是類型安全的,然后使用 @SafeVarargs 對其進行注釋,這樣使用起來就不會令人不愉快。
---
**[Back to contents of the chapter(返回章節目錄)](/Chapter-5/Chapter-5-Introduction.md)**
- **Previous Item(上一條目):[Item 31: Use bounded wildcards to increase API flexibility(使用有界通配符增加 API 的靈活性)](/Chapter-5/Chapter-5-Item-31-Use-bounded-wildcards-to-increase-API-flexibility.md)**
- **Next Item(下一條目):[Item 33: Consider typesafe heterogeneous containers(考慮類型安全的異構容器)](/Chapter-5/Chapter-5-Item-33-Consider-typesafe-heterogeneous-containers.md)**
- Chapter 2. Creating and Destroying Objects(創建和銷毀對象)
- Item 1: Consider static factory methods instead of constructors(考慮以靜態工廠方法代替構造函數)
- Item 2: Consider a builder when faced with many constructor parameters(在面對多個構造函數參數時,請考慮構建器)
- Item 3: Enforce the singleton property with a private constructor or an enum type(使用私有構造函數或枚舉類型實施單例屬性)
- Item 4: Enforce noninstantiability with a private constructor(用私有構造函數實施不可實例化)
- Item 5: Prefer dependency injection to hardwiring resources(依賴注入優于硬連接資源)
- Item 6: Avoid creating unnecessary objects(避免創建不必要的對象)
- Item 7: Eliminate obsolete object references(排除過時的對象引用)
- Item 8: Avoid finalizers and cleaners(避免使用終結器和清除器)
- Item 9: Prefer try with resources to try finally(使用 try-with-resources 優于 try-finally)
- Chapter 3. Methods Common to All Objects(對象的通用方法)
- Item 10: Obey the general contract when overriding equals(覆蓋 equals 方法時應遵守的約定)
- Item 11: Always override hashCode when you override equals(當覆蓋 equals 方法時,總要覆蓋 hashCode 方法)
- Item 12: Always override toString(始終覆蓋 toString 方法)
- Item 13: Override clone judiciously(明智地覆蓋 clone 方法)
- Item 14: Consider implementing Comparable(考慮實現 Comparable 接口)
- Chapter 4. Classes and Interfaces(類和接口)
- Item 15: Minimize the accessibility of classes and members(盡量減少類和成員的可訪問性)
- Item 16: In public classes use accessor methods not public fields(在公共類中,使用訪問器方法,而不是公共字段)
- Item 17: Minimize mutability(減少可變性)
- Item 18: Favor composition over inheritance(優先選擇復合而不是繼承)
- Item 19: Design and document for inheritance or else prohibit it(繼承要設計良好并且具有文檔,否則禁止使用)
- Item 20: Prefer interfaces to abstract classes(接口優于抽象類)
- Item 21: Design interfaces for posterity(為后代設計接口)
- Item 22: Use interfaces only to define types(接口只用于定義類型)
- Item 23: Prefer class hierarchies to tagged classes(類層次結構優于帶標簽的類)
- Item 24: Favor static member classes over nonstatic(靜態成員類優于非靜態成員類)
- Item 25: Limit source files to a single top level class(源文件僅限有單個頂層類)
- Chapter 5. Generics(泛型)
- Item 26: Do not use raw types(不要使用原始類型)
- Item 27: Eliminate unchecked warnings(消除 unchecked 警告)
- Item 28: Prefer lists to arrays(list 優于數組)
- Item 29: Favor generic types(優先使用泛型)
- Item 30: Favor generic methods(優先使用泛型方法)
- Item 31: Use bounded wildcards to increase API flexibility(使用有界通配符增加 API 的靈活性)
- Item 32: Combine generics and varargs judiciously(明智地合用泛型和可變參數)
- Item 33: Consider typesafe heterogeneous containers(考慮類型安全的異構容器)
- Chapter 6. Enums and Annotations(枚舉和注解)
- Item 34: Use enums instead of int constants(用枚舉類型代替 int 常量)
- Item 35: Use instance fields instead of ordinals(使用實例字段替代序數)
- Item 36: Use EnumSet instead of bit fields(用 EnumSet 替代位字段)
- Item 37: Use EnumMap instead of ordinal indexing(使用 EnumMap 替換序數索引)
- Item 38: Emulate extensible enums with interfaces(使用接口模擬可擴展枚舉)
- Item 39: Prefer annotations to naming patterns(注解優于命名模式)
- Item 40: Consistently use the Override annotation(堅持使用 @Override 注解)
- Item 41: Use marker interfaces to define types(使用標記接口定義類型)
- Chapter 7. Lambdas and Streams(λ 表達式和流)
- Item 42: Prefer lambdas to anonymous classes(λ 表達式優于匿名類)
- Item 43: Prefer method references to lambdas(方法引用優于 λ 表達式)
- Item 44: Favor the use of standard functional interfaces(優先使用標準函數式接口)
- Item 45: Use streams judiciously(明智地使用流)
- Item 46: Prefer side effect free functions in streams(在流中使用無副作用的函數)
- Item 47: Prefer Collection to Stream as a return type(優先選擇 Collection 而不是流作為返回類型)
- Item 48: Use caution when making streams parallel(謹慎使用并行流)
- Chapter 8. Methods(方法)
- Item 49: Check parameters for validity(檢查參數的有效性)
- Item 50: Make defensive copies when needed(在需要時制作防御性副本)
- Item 51: Design method signatures carefully(仔細設計方法簽名)
- Item 52: Use overloading judiciously(明智地使用重載)
- Item 53: Use varargs judiciously(明智地使用可變參數)
- Item 54: Return empty collections or arrays, not nulls(返回空集合或數組,而不是 null)
- Item 55: Return optionals judiciously(明智地的返回 Optional)
- Item 56: Write doc comments for all exposed API elements(為所有公開的 API 元素編寫文檔注釋)
- Chapter 9. General Programming(通用程序設計)
- Item 57: Minimize the scope of local variables(將局部變量的作用域最小化)
- Item 58: Prefer for-each loops to traditional for loops(for-each 循環優于傳統的 for 循環)
- Item 59: Know and use the libraries(了解并使用庫)
- Item 60: Avoid float and double if exact answers are required(若需要精確答案就應避免使用 float 和 double 類型)
- Item 61: Prefer primitive types to boxed primitives(基本數據類型優于包裝類)
- Item 62: Avoid strings where other types are more appropriate(其他類型更合適時應避免使用字符串)
- Item 63: Beware the performance of string concatenation(當心字符串連接引起的性能問題)
- Item 64: Refer to objects by their interfaces(通過接口引用對象)
- Item 65: Prefer interfaces to reflection(接口優于反射)
- Item 66: Use native methods judiciously(明智地使用本地方法)
- Item 67: Optimize judiciously(明智地進行優化)
- Item 68: Adhere to generally accepted naming conventions(遵守被廣泛認可的命名約定)
- Chapter 10. Exceptions(異常)
- Item 69: Use exceptions only for exceptional conditions(僅在確有異常條件下使用異常)
- Item 70: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors(對可恢復情況使用 checked 異常,對編程錯誤使用運行時異常)
- Item 71: Avoid unnecessary use of checked exceptions(避免不必要地使用 checked 異常)
- Item 72: Favor the use of standard exceptions(鼓勵復用標準異常)
- Item 73: Throw exceptions appropriate to the abstraction(拋出能用抽象解釋的異常)
- Item 74: Document all exceptions thrown by each method(為每個方法記錄會拋出的所有異常)
- Item 75: Include failure capture information in detail messages(異常詳細消息中應包含捕獲失敗的信息)
- Item 76: Strive for failure atomicity(盡力保證故障原子性)
- Item 77: Don’t ignore exceptions(不要忽略異常)
- Chapter 11. Concurrency(并發)
- Item 78: Synchronize access to shared mutable data(對共享可變數據的同步訪問)
- Item 79: Avoid excessive synchronization(避免過度同步)
- Item 80: Prefer executors, tasks, and streams to threads(Executor、task、流優于直接使用線程)
- Item 81: Prefer concurrency utilities to wait and notify(并發實用工具優于 wait 和 notify)
- Item 82: Document thread safety(文檔應包含線程安全屬性)
- Item 83: Use lazy initialization judiciously(明智地使用延遲初始化)
- Item 84: Don’t depend on the thread scheduler(不要依賴線程調度器)
- Chapter 12. Serialization(序列化)
- Item 85: Prefer alternatives to Java serialization(優先選擇 Java 序列化的替代方案)
- Item 86: Implement Serializable with great caution(非常謹慎地實現 Serializable)
- Item 87: Consider using a custom serialized form(考慮使用自定義序列化形式)
- Item 88: Write readObject methods defensively(防御性地編寫 readObject 方法)
- Item 89: For instance control, prefer enum types to readResolve(對于實例控制,枚舉類型優于 readResolve)
- Item 90: Consider serialization proxies instead of serialized instances(考慮以序列化代理代替序列化實例)