## Chapter 4. Classes and Interfaces(類和接口)
### Item 20: Prefer interfaces to abstract classes(接口優于抽象類)
Java has two mechanisms to define a type that permits multiple implementations: interfaces and abstract classes. Since the introduction of default methods for interfaces in Java 8 [JLS 9.4.3], both mechanisms allow you to provide implementations for some instance methods. A major difference is that to implement the type defined by an abstract class, a class must be a subclass of the abstract class. Because Java permits only single inheritance, this restriction on abstract classes severely constrains their use as type definitions.Any class that defines all the required methods and obeys the general contract is permitted to implement an interface, regardless of where the class resides in the class hierarchy.
Java 有兩種機制來定義允許多種實現的類型:接口和抽象類。由于 Java 8 [JLS 9.4.3]中引入了接口的默認方法,這兩種機制都允許你為一些實例方法提供實現。一個主要區別是,一個類要實現抽象類定義的類型,該類必須是抽象類的子類。因為 Java 只允許單一繼承,這種限制對抽象類而言嚴重制約了它們作為類型定義的使用。任何定義了所有必需的方法并遵守通用約定的類都允許實現接口,而不管該類駐留在類層次結構中何處。
**譯注:**
**1、抽象類的局限:一個類要實現抽象類定義的類型,該類必須是抽象類的子類。因為 Java 只允許單一繼承,這種限制對抽象類而言嚴重制約了它們作為類型定義的使用。**
**2、接口的優點:任何定義了所有必需的方法并遵守通用約定的類都允許實現接口,而不管該類駐留在類層次結構中何處。**
**Existing classes can easily be retrofitted to implement a new interface.** All you have to do is to add the required methods, if they don’t yet exist, and to add an implements clause to the class declaration. For example, many existing classes were retrofitted to implement the Comparable, Iterable, and Autocloseable interfaces when they were added to the platform. Existing classes cannot, in general, be retrofitted to extend a new abstract class. If you want to have two classes extend the same abstract class, you have to place it high up in the type hierarchy where it is an ancestor of both classes. Unfortunately,this can cause great collateral damage to the type hierarchy, forcing all descendants of the new abstract class to subclass it, whether or not it is appropriate.
**可以很容易地對現有類進行改造,以實現新的接口。** 你所要做的就是添加所需的方法(如果它們還不存在的話),并向類聲明中添加一個 implements 子句。例如,許多現有的類在添加到 JDK 時進行了修改,以實現 Comparable、Iterable 和 Autocloseable 接口。一般來說,現有的類不能被修改以擴展新的抽象類。如果你想讓兩個類擴展同一個抽象類,你必須把它放在類型層次結構的高層,作為兩個類的祖先。不幸的是,這可能會對類型層次結構造成巨大的附帶損害,迫使新抽象類的所有后代對其進行子類化,無論它是否合適。
**Interfaces are ideal for defining mixins.** Loosely speaking, a mixin is a type that a class can implement in addition to its “primary type,” to declare that it provides some optional behavior. For example, Comparable is a mixin interface that allows a class to declare that its instances are ordered with respect to other mutually comparable objects. Such an interface is called a mixin because it allows the optional functionality to be “mixed in” to the type’s primary functionality. Abstract classes can’t be used to define mixins for the same reason that they can’t be retrofitted onto existing classes: a class cannot have more than one parent, and there is no reasonable place in the class hierarchy to insert a mixin.
**接口是定義 mixin(混合類型)的理想工具。** 粗略地說,mixin 是類除了「基本類型」之外還可以實現的類型,用于聲明它提供了一些可選的行為。例如,Comparable 是一個 mixin 接口,它允許類的實例可以與其他的可相互比較的對象進行排序。這樣的接口稱為 mixin,因為它允許可選功能「混合」到類型的主要功能中。抽象類不能用于定義 mixin,原因與它們不能被修改到現有類相同:一個類不能有多個父類,而且在類層次結構中沒有插入 mixin 的合理位置。
**Interfaces allow for the construction of nonhierarchical type frameworks.** Type hierarchies are great for organizing some things, but other things don’t fall neatly into a rigid hierarchy. For example, suppose we have an interface representing a singer and another representing a songwriter:
**接口允許構造非層次化類型框架。** 類型層次結構對于組織一些事情很好,但是其他事情不能整齊地歸入嚴格的層次結構。例如,假設我們有一個代表歌手的接口和另一個代表詞曲作者的接口:
```
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(int chartPosition);
}
```
In real life, some singers are also songwriters. Because we used interfaces rather than abstract classes to define these types, it is perfectly permissible for a single class to implement both Singer and Songwriter. In fact, we can define a third interface that extends both Singer and Songwriter and adds new methods that are appropriate to the combination:
在現實生活中,一些歌手也是詞曲作者。因為我們使用接口而不是抽象類來定義這些類型,所以完全允許單個類同時實現歌手和詞曲作者。事實上,我們可以定義第三個接口,擴展歌手和詞曲作者,并添加適合這種組合的新方法:
```
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
```
You don’t always need this level of flexibility, but when you do, interfaces are a lifesaver. The alternative is a bloated class hierarchy containing a separate class for every supported combination of attributes. If there are n attributes in the type system, there are 2n possible combinations that you might have to support. This is what’s known as a combinatorial explosion. Bloated class hierarchies can lead to bloated classes with many methods that differ only in the type of their arguments because there are no types in the class hierarchy to capture common behaviors.
你并不總是需要這種級別的靈活性,但是當你需要時,接口就是救星。另一種選擇是一個臃腫的類層次結構,它為每個受支持的屬性組合包含一個單獨的類。如果類型系統中有 n 個屬性,那么可能需要支持 2<sup>n</sup>種組合。這就是所謂的組合爆炸。臃腫的類層次結構可能導致類也臃腫,其中許多方法只在其參數的類型上有所不同,因為類層次結構中沒有類型來捕獲公共行為。
Interfaces enable safe, powerful functionality enhancements via the wrapper class idiom (Item 18). If you use abstract classes to define types, you leave the programmer who wants to add functionality with no alternative but inheritance. The resulting classes are less powerful and more fragile than wrapper classes.
通過 [Item-18](/Chapter-4/Chapter-4-Item-18-Favor-composition-over-inheritance.md) 介紹的包裝類,接口能夠支持安全、強大的功能增強。如果你使用抽象類來定義類型,那么希望添加功能的程序員除了繼承之外別無選擇。最終生成的類不如包裝類強大,也更脆弱。
When there is an obvious implementation of an interface method in terms of other interface methods, consider providing implementation assistance to programmers in the form of a default method. For an example of this technique, see the removeIf method on page 104. If you provide default methods, be sure to document them for inheritance using the @implSpec Javadoc tag (Item 19).
如果接口方法的實現與其他接口方法類似,那么可以考慮以默認方法的形式為程序員提供實現幫助。有關此技術的示例,請參閱第 104 頁的 removeIf 方法。如果提供了默認方法,請使用 `@implSpec` 標簽,并確保在文檔中記錄他們的繼承關系([Item-19](/Chapter-4/Chapter-4-Item-19-Design-and-document-for-inheritance-or-else-prohibit-it.md))。
There are limits on how much implementation assistance you can provide with default methods. Although many interfaces specify the behavior of Object methods such as equals and hashCode, you are not permitted to provide default methods for them. Also, interfaces are not permitted to contain instance fields or nonpublic static members (with the exception of private static methods). Finally, you can’t add default methods to an interface that you don’t control.
默認方法為實現提供的幫助有限。盡管許多接口指定了諸如 equals 和 hashCode 等對象方法的行為,但是不允許為它們提供默認方法。此外,接口不允許包含實例字段或非公共靜態成員(私有靜態方法除外)。最后,你不能向你不控制的接口添加默認方法。
You can, however, combine the advantages of interfaces and abstract classes by providing an abstract skeletal implementation class to go with an interface. The interface defines the type, perhaps providing some default methods, while the skeletal implementation class implements the remaining non-primitive interface methods atop the primitive interface methods. Extending a skeletal implementation takes most of the work out of implementing an interface. This is the Template Method pattern [Gamma95].
但是,你可以通過提供一個抽象骨架實現類來結合接口和抽象類的優點。接口定義了類型,可能提供了一些默認方法,而骨架實現類在基本接口方法之上實現了其余的非基本接口方法。擴展骨架實現需要完成實現接口的大部分工作。這是模板方法模式 [Gamma95]。
By convention, skeletal implementation classes are called AbstractInterface, where Interface is the name of the interface they implement. For example, the Collections Framework provides a skeletal implementation to go along with each main collection interface: AbstractCollection, AbstractSet, AbstractList, and AbstractMap. Arguably it would have made sense to call them SkeletalCollection, SkeletalSet, SkeletalList, and SkeletalMap, but the Abstract convention is now firmly established. When properly designed, skeletal implementations (whether a separate abstract class, or consisting solely of default methods on an interface) can make it very easy for programmers to provide their own implementations of an interface. For example, here’s a static factory method containing a complete, fully functional List implementation atop AbstractList:
按照慣例,骨架實現類稱為 AbstractInterface,其中 Interface 是它們實現的接口的名稱。例如,Collections Framework 提供了一個骨架實現來配合每個主要的集合接口:AbstractCollection、AbstractSet、AbstractList 和 AbstractMap。可以說,將它們稱為 SkeletalCollection、SkeletalSet、SkeletalList 和 SkeletalMap 是有意義的,但 Abstract 的用法現在已經根深蒂固。如果設計得當,骨架實現(無論是單獨的抽象類,還是僅僅由接口上的默認方法組成)可以使程序員非常容易地提供他們自己的接口實現。例如,這里有一個靜態工廠方法,它在 AbstractList 上包含一個完整的、功能完整的 List 實現:
```
// Concrete implementation built atop skeletal implementation
static List<Integer> intArrayAsList(int[] a) {
Objects.requireNonNull(a);
// The diamond operator is only legal here in Java 9 and later
// If you're using an earlier release, specify <Integer>
return new AbstractList<>() {
@Override
public Integer get(int i) {
return a[i]; // Autoboxing (Item 6)
}
@Override
public Integer set(int i, Integer val) {
int oldVal = a[i];
a[i] = val; // Auto-unboxing
return oldVal; // Autoboxing
}
@Override
public int size() {
return a.length;
}
};
}
```
When you consider all that a List implementation does for you, this example is an impressive demonstration of the power of skeletal implementations. Incidentally, this example is an Adapter [Gamma95] that allows an int array to be viewed as a list of Integer instances. Because of all the translation back and forth between int values and Integer instances (boxing and unboxing), its performance is not terribly good. Note that the implementation takes the form of an anonymous class (Item 24).
當你考慮到 List 實現為你做的所有事情時,這個例子是一個令人印象深刻的演示,體現了骨架實現的強大功能。順便說一句,這個示例是一個 Adapter(適配器)[Gamma95],它允許將 int 數組視為 Integer 實例的 list。因為在 int 值和 Integer 實例(裝箱和拆箱)之間來回轉換,所以它的性能不是很好。注意,實現的形式是匿名類([Item-24](/Chapter-4/Chapter-4-Item-24-Favor-static-member-classes-over-nonstatic.md))。
The beauty of skeletal implementation classes is that they provide all of the implementation assistance of abstract classes without imposing the severe constraints that abstract classes impose when they serve as type definitions. For most implementors of an interface with a skeletal implementation class, extending this class is the obvious choice, but it is strictly optional. If a class cannot be made to extend the skeletal implementation, the class can always implement the interface directly. The class still benefits from any default methods present on the interface itself. Furthermore, the skeletal implementation can still aid the implementor’s task. The class implementing the interface can forward invocations of interface methods to a contained instance of a private inner class that extends the skeletal implementation. This technique, known as simulated multiple inheritance, is closely related to the wrapper class idiom discussed in Item 18. It provides many of the benefits of multiple inheritance, while avoiding the pitfalls.
骨架實現類的美妙之處在于,它們提供了抽象類的所有實現幫助,而不像抽象類作為類型定義時那樣受到嚴格的約束。對于具有骨架實現類的接口的大多數實現來說,擴展這個類是顯而易見的選擇,但它并不是必需的。如果不能使類擴展骨架實現,則類總是可以直接實現接口。類仍然受益于接口本身的任何默認方法。此外,骨架實現仍然可以幫助實現人員完成任務。實現接口的類可以將接口方法的調用轉發給擴展骨架實現的私有內部類的包含實例。這種技術稱為模擬多重繼承,與[Item-18](/Chapter-4/Chapter-4-Item-18-Favor-composition-over-inheritance.md)中討論的包裝類密切相關。它提供了多重繼承的許多好處,同時避免了缺陷。
Writing a skeletal implementation is a relatively simple, if somewhat tedious, process. First, study the interface and decide which methods are the primitives in terms of which the others can be implemented. These primitives will be the abstract methods in your skeletal implementation. Next, provide default methods in the interface for all of the methods that can be implemented directly atop the primitives, but recall that you may not provide default methods for Object methods such as equals and hashCode. If the primitives and default methods cover the interface, you’re done, and have no need for a skeletal implementation class. Otherwise, write a class declared to implement the interface, with implementations of all of the remaining interface methods. The class may contain any nonpublic fields ands methods appropriate to the task.
編寫一個骨架實現是一個相對簡單的過程,盡管有點乏味。首先,研究接口并決定哪些方法是基本方法,以便其他方法可以根據它們實現。這些基本方法將是你的骨架實現中的抽象方法。接下來,在接口中為所有可以直接在基本方法之上實現的方法提供默認方法,但請記住,你可能不會為諸如 equals 和 hashCode 之類的對象方法提供默認方法。如果基本方法和默認方法覆蓋了接口,那么就完成了,不需要一個骨架實現類。否則,編寫一個聲明為實現接口的類,并實現所有剩余的接口方法。該類可能包含任何適合于任務的非公共字段和方法。
As a simple example, consider the Map.Entry interface. The obvious primitives are getKey, getValue, and (optionally) setValue. The interface specifies the behavior of equals and hashCode, and there is an obvious implementation of toString in terms of the primitives. Since you are not allowed to provide default implementations for the Object methods, all implementations are placed in the skeletal implementation class:
作為一個簡單的例子,考慮一下 `Map.Entry` 接口。最明顯的基本方法是 getKey、getValue 和(可選的)setValue。該接口指定了 equals 和 hashCode 的行為,并且在基本方法方面有 toString 的明顯實現。由于不允許為對象方法提供默認實現,所有實現都放在骨架實現類中:
```
// Skeletal implementation class
public abstract class AbstractMapEntry<K,V> implements Map.Entry<K,V> {
// Entries in a modifiable map must override this method
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
// Implements the general contract of Map.Entry.equals
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry) o;
return Objects.equals(e.getKey(), getKey()) && Objects.equals(e.getValue(), getValue());
}
// Implements the general contract of Map.Entry.hashCode
@Override public int hashCode() {
return Objects.hashCode(getKey())^ Objects.hashCode(getValue());
}
@Override public String toString() {
return getKey() + "=" + getValue();
}
}
```
Note that this skeletal implementation could not be implemented in the Map.Entry interface or as a subinterface because default methods are not permitted to override Object methods such as equals, hashCode, and toString.
注意,這個骨架實現不能在 `Map.Entry` 接口或子接口中實現,因為不允許默認方法覆蓋諸如 equals、hashCode 和 toString 等對象方法。
Because skeletal implementations are designed for inheritance, you should follow all of the design and documentation guidelines in Item 19. For brevity’s sake, the documentation comments were omitted from the previous example, but good documentation is absolutely essential in a skeletal implementation, whether it consists of default methods on an interface or a separate abstract class.
因為骨架實現是為繼承而設計的,所以你應該遵循 [Item-19](/Chapter-4/Chapter-4-Item-19-Design-and-document-for-inheritance-or-else-prohibit-it.md) 中的所有設計和文檔指南。為了簡潔起見,在前面的示例中省略了文檔注釋,但是優秀的文檔對于骨架實現來說是絕對必要的,不管它是由接口上的默認方法還是單獨的抽象類組成。
A minor variant on the skeletal implementation is the simple implementation, exemplified by AbstractMap.SimpleEntry. A simple implementation is like a skeletal implementation in that it implements an interface and is designed for inheritance, but it differs in that it isn’t abstract: it is the simplest possible working implementation. You can use it as it stands or subclass it as circumstances warrant.
骨架實現的一個小變種是簡單實現,例如 `AbstractMap.SimpleEntry`。一個簡單的實現就像一個骨架實現,因為它實現了一個接口,并且是為繼承而設計的,但是它的不同之處在于它不是抽象的:它是最簡單的工作實現。你可以根據它的狀態使用它,也可以根據情況對它進行子類化。
To summarize, an interface is generally the best way to define a type that permits multiple implementations. If you export a nontrivial interface, you should strongly consider providing a skeletal implementation to go with it. To the extent possible, you should provide the skeletal implementation via default methods on the interface so that all implementors of the interface can make use of it. That said, restrictions on interfaces typically mandate that a skeletal implementation take the form of an abstract class.
總之,接口通常是定義允許多種實現的類型的最佳方法。如果導出了一個重要的接口,則應該強烈考慮提供一個骨架實現。盡可能地,你應該通過接口上的默認方法提供骨架實現,以便接口的所有實現者都可以使用它。也就是說,對接口的限制通常要求框架實現采用抽象類的形式。
---
**[Back to contents of the chapter(返回章節目錄)](/Chapter-4/Chapter-4-Introduction.md)**
- **Previous Item(上一條目):[Item 19: Design and document for inheritance or else prohibit it(繼承要設計良好并且具有文檔,否則禁止使用)](/Chapter-4/Chapter-4-Item-19-Design-and-document-for-inheritance-or-else-prohibit-it.md)**
- **Next Item(下一條目):[Item 21: Design interfaces for posterity(為后代設計接口)](/Chapter-4/Chapter-4-Item-21-Design-interfaces-for-posterity.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(考慮以序列化代理代替序列化實例)