## Chapter 3. Methods Common to All Objects(对象的通用方法)
### Item 14: Consider implementing Comparable(考虑实现 Comparable 接口)
Unlike the other methods discussed in this chapter, the compareTo method is not declared in Object. Rather, it is the sole method in the Comparable interface. It is similar in character to Object’s equals method, except that it permits order comparisons in addition to simple equality comparisons, and it is generic. By implementing Comparable, a class indicates that its instances have a natural ordering. Sorting an array of objects that implement Comparable is as simple as this:
与本章讨论的其他方法不同,compareTo 方法不是在 Object 中声明的。相反,它是 Comparable 接口中的唯一方法。它在性质上类似于 Object 的 equals 方法,除了简单的相等比较之外,它还允许顺序比较,而且它是通用的。一个类实现 Comparable,表明实例具有自然顺序。对实现 Comparable 的对象数组进行排序非常简单:
```
Arrays.sort(a);
```
It is similarly easy to search, compute extreme values, and maintain automatically sorted collections of Comparable objects. For example, the following program, which relies on the fact that String implements Comparable, prints an alphabetized list of its command-line arguments with duplicates eliminated:
类似地,搜索、计算极值和维护 Comparable 对象的自动排序集合也很容易。例如,下面的程序依赖于 String 实现 Comparable 这一事实,将命令行参数列表按字母顺序打印出来,并消除重复:
```
public class WordList {
public static void main(String[] args) {
Set<String> s = new TreeSet<>();
Collections.addAll(s, args);
System.out.println(s);
}
}
```
By implementing Comparable, you allow your class to interoperate with all of the many generic algorithms and collection implementations that depend on this interface. You gain a tremendous amount of power for a small amount of effort. Virtually all of the value classes in the Java platform libraries, as well as all enum types (Item 34), implement Comparable. If you are writing a value class with an obvious natural ordering, such as alphabetical order, numerical order, or chronological order, you should implement the Comparable interface:
通过让类实现 Comparable,就可与依赖于此接口的所有通用算法和集合实现进行互操作。你只需付出一点点努力就能获得强大的功能。实际上,Java 库中的所有值类以及所有枚举类型([Item-34](/Chapter-6/Chapter-6-Item-34-Use-enums-instead-of-int-constants.md))都实现了 Comparable。如果编写的值类具有明显的自然顺序,如字母顺序、数字顺序或时间顺序,则应实现 Comparable 接口:
```
public interface Comparable<T> {
int compareTo(T t);
}
```
The general contract of the compareTo method is similar to that of equals:
compareTo 方法的一般约定类似于 equals 方法:
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Throws ClassCastException if the specified object’s type prevents it from being compared to this object.
将一个对象与指定的对象进行顺序比较。当该对象小于、等于或大于指定对象时,对应返回一个负整数、零或正整数。如果指定对象的类型阻止它与该对象进行比较,则抛出 ClassCastException。
In the following description, the notation sgn(expression) designates the mathematical signum function, which is defined to return -1, 0, or 1,according to whether the value of expression is negative, zero, or positive.
在下面的描述中,`sgn(expression)` 表示数学中的符号函数,它被定义为:根据传入表达式的值是负数、零或正数,对应返回 -1、0 或 1。
- The implementor must ensure that sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception if and only if y.compareTo(x) throws an exception.)
实现者必须确保所有 x 和 y 满足 `sgn(x.compareTo(y)) == -sgn(y.compareTo(x))`(这意味着 `x.compareTo(y)` 当且仅当 `y.compareTo(x)` 抛出异常时才抛出异常)。
- The implementor must also ensure that the relation is transitive: (x.compareTo(y) > 0 && y.compareTo(z) > 0) implies x.compareTo(z) > 0.
实现者还必须确保关系是可传递的:`(x.compareTo(y) > 0 && y.compareTo(z) > 0)` 意味着 `x.compareTo(z) > 0`。
- Finally, the implementor must ensure that x.compareTo(y) == 0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)),for all z.
最后,实现者必须确保 `x.compareTo(y) == 0` 时,所有的 z 满足 `sgn(x.compareTo(z)) == sgn(y.compareTo(z))`。
- It is strongly recommended, but not required, that (x.compareTo(y)== 0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is “Note: This class has a natural ordering that is inconsistent with equals.”
强烈建议 `(x.compareTo(y)== 0) == (x.equals(y))` 成立,但不是必需的。一般来说,任何实现 Comparable 接口并违反此条件的类都应该清楚地注明这一事实。推荐使用的表述是「注意:该类的自然顺序与 equals 不一致。」
Don’t be put off by the mathematical nature of this contract. Like the equals contract (Item 10), this contract isn’t as complicated as it looks. Unlike the equals method, which imposes a global equivalence relation on all objects,compareTo doesn’t have to work across objects of different types: when confronted with objects of different types, compareTo is permitted to throw ClassCastException. Usually, that is exactly what it does. The contract does permit intertype comparisons, which are typically defined in an interface implemented by the objects being compared.
不要被这些约定的数学性质所影响。就像 equals 约定([Item-10](/Chapter-3/Chapter-3-Item-10-Obey-the-general-contract-when-overriding-equals.md))一样,这个约定并不像看起来那么复杂。与 equals 方法不同,equals 方法对所有对象都施加了全局等价关系,compareTo 不需要跨越不同类型的对象工作:当遇到不同类型的对象时,compareTo 允许抛出 ClassCastException。通常,它就是这么做的。该约定确实允许类型间比较,这种比较通常在被比较对象实现的接口中定义。
Just as a class that violates the hashCode contract can break other classes that depend on hashing, a class that violates the compareTo contract can break other classes that depend on comparison. Classes that depend on comparison include the sorted collections TreeSet and TreeMap and the utility classes Collections and Arrays, which contain searching and sorting algorithms.
就像违反 hashCode 约定的类可以破坏依赖 hash 的其他类一样,违反 compareTo 约定的类也可以破坏依赖 Comparable 的其他类。依赖 Comparable 的类包括排序集合 TreeSet 和 TreeMap,以及实用工具类 Collections 和 Arrays,它们都包含搜索和排序算法。
Let’s go over the provisions of the compareTo contract. The first provision says that if you reverse the direction of a comparison between two object references, the expected thing happens: if the first object is less than the second,then the second must be greater than the first; if the first object is equal to the second, then the second must be equal to the first; and if the first object is greater than the second, then the second must be less than the first. The second provision says that if one object is greater than a second and the second is greater than a third, then the first must be greater than the third. The final provision says that all objects that compare as equal must yield the same results when compared to any other object.
让我们看一下 compareTo 约定的细节。第一个规定指出,如果你颠倒两个对象引用之间的比较的方向,就应当发生这样的情况:如果第一个对象小于第二个对象,那么第二个对象必须大于第一个;如果第一个对象等于第二个对象,那么第二个对象一定等于第一个对象;如果第一个对象大于第二个对象,那么第二个对象一定小于第一个对象。第二个规定指出,如果一个对象大于第二个,第二个大于第三个,那么第一个对象一定大于第三个对象。最后一个规定指出,所有 compareTo 结果为相等的对象分别与任何其他对象相比,必须产生相同的结果。
One consequence of these three provisions is that the equality test imposed by a compareTo method must obey the same restrictions imposed by the equals con-tract: reflexivity, symmetry, and transitivity. Therefore, the same caveat applies: there is no way to extend an instantiable class with a new value component while preserving the compareTo contract, unless you are willing to forgo the benefits of object-oriented abstraction (Item 10). The same workaround applies, too. If you want to add a value component to a class that implements Comparable, don’t extend it; write an unrelated class containing an instance of the first class. Then provide a “view” method that returns the contained instance. This frees you to implement whatever compareTo method you like on the containing class, while allowing its client to view an instance of the containing class as an instance of the contained class when needed.
这三种规定的一个结果是,由 compareTo 方法进行的相等性检验必须遵守由 equals 约定进行的相同的限制:反身性、对称性和传递性。因此,同样的警告也适用于此:除非你愿意放弃面向对象的抽象优点([Item-10](/Chapter-3/Chapter-3-Item-10-Obey-the-general-contract-when-overriding-equals.md)),否则无法在保留 compareTo 约定的同时使用新值组件扩展可实例化类。同样的解决方案也适用。如果要向实现 Comparable 的类中添加值组件,不要继承它;编写一个不相关的类,其中包含第一个类的实例。然后提供返回所包含实例的「视图」方法。这使你可以自由地在包含类上实现你喜欢的任何 compareTo 方法,同时允许它的客户端在需要时将包含类的实例视为包含类的实例。
The final paragraph of the compareTo contract, which is a strong suggestion rather than a true requirement, simply states that the equality test imposed by the compareTo method should generally return the same results as the equals method. If this provision is obeyed, the ordering imposed by the compareTo method is said to be consistent with equals. If it’s violated, the ordering is said to be inconsistent with equals. A class whose compareTo method imposes an order that is inconsistent with equals will still work, but sorted collections containing elements of the class may not obey the general contract of the appropriate collection interfaces (Collection, Set, or Map). This is because the general contracts for these interfaces are defined in terms of the equals method, but sorted collections use the equality test imposed by compareTo in place of equals. It is not a catastrophe if this happens, but it’s something to be aware of.
compareTo 约定的最后一段是一个强烈的建议,而不是一个真正的要求,它只是简单地说明了 compareTo 方法所施加的同等性检验通常应该与 equals 方法返回相同的结果。如果遵守了这一规定,则 compareTo 方法所施加的排序与 equals 方法一致。如果违反这条建议,那么它的顺序就与 equals 不一致。如果一个类的 compareTo 方法强加了一个与 equals 不一致的顺序,那么这个类仍然可以工作,但是包含该类元素的有序集合可能无法遵守集合接口(Collection、Set 或 Map)的一般约定。这是因为这些接口的一般约定是根据 equals 方法定义的,但是有序集合使用 compareTo 代替了 equals 实施同等性检验。如果发生这种情况,这不是一场灾难,但这是需要注意的。
For example, consider the BigDecimal class, whose compareTo method is inconsistent with equals. If you create an empty HashSet instance and then add new BigDecimal("1.0") and new BigDecimal("1.00"),the set will contain two elements because the two BigDecimal instances added to the set are unequal when compared using the equals method. If,however, you perform the same procedure using a TreeSet instead of a HashSet, the set will contain only one element because the two BigDecimal instances are equal when compared using the compareTo method. (See the BigDecimal documentation for details.)
例如,考虑 BigDecimal 类,它的 compareTo 方法与 equals 不一致。如果你创建一个空的 HashSet 实例,然后添加 `new BigDecimal("1.0")` 和 `new BigDecimal("1.00")`,那么该 HashSet 将包含两个元素,因为添加到该集合的两个 BigDecimal 实例在使用 equals 方法进行比较时结果是不相等的。但是,如果你使用 TreeSet 而不是 HashSet 执行相同的过程,那么该集合将只包含一个元素,因为使用 compareTo 方法比较两个 BigDecimal 实例时结果是相等的。(有关详细信息,请参阅 BigDecimal 文档。)
Writing a compareTo method is similar to writing an equals method, but there are a few key differences. Because the Comparable interface is parameterized, the compareTo method is statically typed, so you don’t need to type check or cast its argument. If the argument is of the wrong type, the invocation won’t even compile. If the argument is null, the invocation should throw a NullPointerException, and it will, as soon as the method attempts to access its members.
编写 compareTo 方法类似于编写 equals 方法,但是有一些关键的区别。因为 Comparable 接口是参数化的,compareTo 方法是静态类型的,所以不需要进行类型检查或强制转换它的参数。如果参数类型错误,则该调用将不能编译。如果参数为 null,则调用应该抛出 NullPointerException,并且在方法尝试访问其成员时抛出该异常。
In a compareTo method, fields are compared for order rather than equality.To compare object reference fields, invoke the compareTo method recursively. If a field does not implement Comparable or you need a nonstandard ordering, use a Comparator instead. You can write your own comparator or use an existing one, as in this compareTo method for CaseInsensitiveString in Item 10:
在 compareTo 方法中,字段是按顺序而不是按同等性来比较的。要比较对象引用字段,要递归调用 compareTo 方法。如果一个字段没有实现 Comparable,或者需要一个非标准的排序,那么应使用 Comparator。可以编写自定义的比较器,或使用现有的比较器,如 [Item-10](/Chapter-3/Chapter-3-Item-10-Obey-the-general-contract-when-overriding-equals.md) 中 CaseInsensitiveString 的 compareTo 方法:
```
// Single-field Comparable with object reference field
public final class CaseInsensitiveString implements Comparable<CaseInsensitiveString> {
public int compareTo(CaseInsensitiveString cis) {
return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s);
} ... // Remainder omitted
}
```
Note that CaseInsensitiveString implements `Comparable<CaseInsensitiveString>`. This means that a CaseInsensitiveString reference can be compared only to another CaseInsensitiveString reference. This is the normal pattern to follow when declaring a class to implement Comparable.
注意 CaseInsensitiveString 实现了 `Comparable<CaseInsensitiveString>`。这意味着 CaseInsensitiveString 引用只能与另一个 CaseInsensitiveString 引用进行比较。这是在声明实现 Comparable 的类时要遵循的常规模式。
Prior editions of this book recommended that compareTo methods compare integral primitive fields using the relational operators < and >, and floating point primitive fields using the static methods Double.compare and Float.compare. In Java 7, static compare methods were added to all of Java’s boxed primitive classes. **Use of the relational operators < and > in compareTo methods is verbose and error-prone and no longer recommended.**
本书的旧版本建议 compareTo 方法使用关系运算符 < 和 > 来比较整数基本类型字段,使用静态方法 `Double.compare` 和 `Float.compare` 来比较浮点基本类型字段。在 Java 7 中,静态比较方法被添加到所有 Java 的包装类中。**在 compareTo 方法中使用关系运算符 < 和 > 冗长且容易出错,因此不再推荐使用。**
If a class has multiple significant fields, the order in which you compare them is critical. Start with the most significant field and work your way down. If a comparison results in anything other than zero (which represents equality),you’re done; just return the result. If the most significant field is equal, compare the next-most-significant field, and so on, until you find an unequal field or compare the least significant field. Here is a compareTo method for the PhoneNumber class in Item 11 demonstrating this technique:
如果一个类有多个重要字段,那么比较它们的顺序非常关键。从最重要的字段开始,一步步往下。如果比较的结果不是 0(用 0 表示相等),那么就完成了;直接返回结果。如果最重要的字段是相等的,就比较下一个最重要的字段,以此类推,直到找到一个不相等的字段或比较到最不重要的字段为止。下面是 [Item-11](/Chapter-3/Chapter-3-Item-11-Always-override-hashCode-when-you-override-equals.md) 中 PhoneNumber 类的 compareTo 方法,演示了这种技术:
```
// Multiple-field Comparable with primitive fields
public int compareTo(PhoneNumber pn) {
int result = Short.compare(areaCode, pn.areaCode);
if (result == 0) {
result = Short.compare(prefix, pn.prefix);
if (result == 0)
result = Short.compare(lineNum, pn.lineNum);
}
return result;
}
```
In Java 8, the Comparator interface was outfitted with a set of comparator construction methods, which enable fluent construction of comparators. These comparators can then be used to implement a compareTo method, as required by the Comparable interface. Many programmers prefer the conciseness of this approach, though it does come at a modest performance cost: sorting arrays of PhoneNumber instances is about 10% slower on my machine. When using this approach, consider using Java’s static import facility so you can refer to static comparator construction methods by their simple names for clarity and brevity. Here’s how the compareTo method for PhoneNumber looks using this approach:
在 Java 8 中,Comparator 接口配备了一组比较器构造方法,可以流畅地构造比较器。然后可以使用这些比较器来实现 Comparator 接口所要求的 compareTo 方法。许多程序员更喜欢这种方法的简明,尽管它存在一些性能成本:在我的机器上,PhoneNumber 实例的数组排序要慢 10% 左右。在使用这种方法时,请考虑使用 Java 的静态导入功能,这样你就可以通过静态比较器构造方法的简单名称来引用它们,以获得清晰和简洁。下面是 PhoneNumber 类的 compareTo 方法改进后的样子:
```
// Comparable with comparator construction methods
private static final Comparator<PhoneNumber> COMPARATOR = comparingInt((PhoneNumber pn) -> pn.areaCode)
.thenComparingInt(pn -> pn.prefix)
.thenComparingInt(pn -> pn.lineNum);
public int compareTo(PhoneNumber pn) {
return COMPARATOR.compare(this, pn);
}
```
**译注 1:示例代码默认使用了静态导入:`import static java.util.Comparator.comparingInt;`**
**译注 2:comparingInt 及 thenComparingInt 的文档描述**
```
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
Accepts a function that extracts an int sort key from a type T, and returns a Comparator<T> that compares by that sort key.
The returned comparator is serializable if the specified function is also serializable.
接受从类型 T 中提取 int 排序 key 的函数,并返回与该排序 key 进行比较的 Comparator<T>。
如果指定的函数是可序列化的,则返回的比较器也是可序列化的。
Type Parameters:
T - the type of element to be compared
Parameters:
keyExtractor - the function used to extract the integer sort key
Returns:
a comparator that compares by an extracted key
Throws:
NullPointerException - if the argument is null
Since:
1.8
```
```
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
Returns a lexicographic-order comparator with a function that extracts a int sort key.
Implementation Requirements:
This default implementation behaves as if thenComparing(comparingInt(keyExtractor)).
返回具有提取 int 排序 key 的函数的字典顺序比较器。
实现要求:
此默认实现的行为类似于 thenComparing(comparingInt(keyExtractor))。
Parameters:
keyExtractor - the function used to extract the integer sort key
Returns:
a lexicographic-order comparator composed of this and then the int sort key
Throws:
NullPointerException - if the argument is null.
Since:
1.8
```
This implementation builds a comparator at class initialization time, using two comparator construction methods. The first is comparingInt. It is a static method that takes a key extractor function that maps an object reference to a key of type int and returns a comparator that orders instances according to that key.In the previous example, comparingInt takes a lambda () that extracts the area code from a PhoneNumber and returns a `Comparator<PhoneNumber>` that orders phone numbers according to their area codes. Note that the lambda explicitly specifies the type of its input parameter (PhoneNumber pn). It turns out that in this situation, Java’s type inference isn’t powerful enough to figure the type out for itself, so we’re forced to help it in order to make the program compile.
这个实现在类初始化时使用两个比较器构造方法构建一个比较器。第一个是 comparingInt。它是一个静态方法,接受一个 key 提取器函数,该函数将对象引用映射到 int 类型的 key ,并返回一个比较器,比较器根据该 key 对实例进行排序。在上述的示例中,comparingInt 使用 lambda 表达式从 PhoneNumber 中提取 areaCode,并返回 `Comparator<PhoneNumber>`,按区号来排序电话号码。注意,lambda 表达式显式地指定其输入参数的类型为 PhoneNumber。事实证明,在这种情况下,Java 的类型推断并没有强大到足以自己判断类型,因此我们不得不帮助它来编译程序。
If two phone numbers have the same area code, we need to further refine the comparison, and that’s exactly what the second comparator construction method,thenComparingInt, does. It is an instance method on Comparator that takes an int key extractor function, and returns a comparator that first applies the original comparator and then uses the extracted key to break ties. You can stack up as many calls to thenComparingInt as you like, resulting in a lexicographic ordering. In the example above, we stack up two calls to thenComparingInt, resulting in an ordering whose secondary key is the prefix and whose tertiary key is the line number. Note that we did not have to specify the parameter type of the key extractor function passed to either of the calls to thenComparingInt: Java’s type inference was smart enough to figure this one out for itself.
如果两个电话号码有相同的区号,我们需要进一步改进比较,这正是第二个 comparator 构造方法 thenComparingInt 所做的。它是 Comparator 上的一个实例方法,它接受一个 int 类型的 key 提取函数,并返回一个比较器,该比较器首先应用原始比较器,然后使用提取的 key 来断开连接。你可以任意堆叠对 thenComparingInt 的调用,从而形成字典顺序。在上面的例子中,我们将两个对 thenComparingInt 的调用叠加起来,得到一个排序,它的第二个 key 是 prefix,而第三个 key 是 lineNum。注意,我们不必指定传递给两个调用 thenComparingInt 的 key 提取器函数的参数类型:Java 的类型推断足够智能,可以自行解决这个问题。
The Comparator class has a full complement of construction methods.There are analogues to comparingInt and thenComparingInt for the primitive types long and double. The int versions can also be used for narrower integral types, such as short, as in our PhoneNumber example. The double versions can also be used for float. This provides coverage of all of Java’s numerical primitive types.
Comparator 类具有完整的构造方法。对于 long 和 double 的基本类型,有类似 comparingInt 和 thenComparingInt 的方法。int 版本还可以用于范围更小的整数类型,如 PhoneNumber 示例中的 short。double 版本也可以用于 float。Comparator 类提供的构造方法覆盖了所有 Java 数值基本类型。
There are also comparator construction methods for object reference types.The static method, named comparing, has two overloadings. One takes a key extractor and uses the keys’ natural order. The second takes both a key extractor and a comparator to be used on the extracted keys. There are three overloadings of the instance method, which is named thenComparing. One overloading takes only a comparator and uses it to provide a secondary order. A second overloading takes only a key extractor and uses the key’s natural order as a secondary order. The final overloading takes both a key extractor and a comparator to be used on the extracted keys.
也有对象引用类型的比较器构造方法。静态方法名为 compare,它有两个重载。一个是使用 key 提取器并使用 key 的自然顺序。第二种方法同时使用 key 提取器和比较器对提取的 key 进行比较。实例方法有三种重载,称为 thenComparing。一个重载只需要一个比较器并使用它来提供一个二级顺序。第二个重载只接受一个 key 提取器,并将 key 的自然顺序用作二级顺序。最后的重载需要一个 key 提取器和一个比较器来对提取的 key 进行比较。
Occasionally you may see compareTo or compare methods that rely on the fact that the difference between two values is negative if the first value is less than the second, zero if the two values are equal, and positive if the first value is greater. Here is an example:
有时候,你可能会看到 compareTo 或 compare 方法,它们依赖于以下事实:如果第一个值小于第二个值,则两个值之间的差为负;如果两个值相等,则为零;如果第一个值大于零,则为正。下面是一个例子:
```
// BROKEN difference-based comparator - violates transitivity!
static Comparator<Object> hashCodeOrder = new Comparator<>() {
public int compare(Object o1, Object o2) {
return o1.hashCode() - o2.hashCode();
}
};
```
Do not use this technique. It is fraught with danger from integer overflow and IEEE 754 floating point arithmetic artifacts [JLS 15.20.1, 15.21.1]. Furthermore,the resulting methods are unlikely to be significantly faster than those written using the techniques described in this item. Use either a static compare method:
不要使用这种技术。它充满了来自整数溢出和 IEEE 754 浮点运算构件的危险 [JLS 15.20.1, 15.21.1]。此外,生成的方法不太可能比使用本项目中描述的技术编写的方法快得多。应使用静态比较方法:
```
// Comparator based on static compare method
static Comparator<Object> hashCodeOrder = new Comparator<>() {
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
};
```
or a comparator construction method:
或比较器构造方法:
```
// Comparator based on Comparator construction method
static Comparator<Object> hashCodeOrder = Comparator
.comparingInt(o -> o.hashCode());
```
In summary, whenever you implement a value class that has a sensible ordering, you should have the class implement the Comparable interface so that its instances can be easily sorted, searched, and used in comparison-based collections. When comparing field values in the implementations of the compareTo methods, avoid the use of the < and > operators. Instead, use the static compare methods in the boxed primitive classes or the comparator construction methods in the Comparator interface.
总之,无论何时实现具有排序性质的值类,都应该让类实现 Comparable 接口,这样就可以轻松地对实例进行排序、搜索,并与依赖于此接口的集合实现进行互操作。在 compareTo 方法的实现中比较字段值时,避免使用 < 和 > 操作符,应使用包装类中的静态比较方法或 Comparator 接口中的 comparator 构造方法。
---
**[Back to contents of the chapter(返回章节目录)](/Chapter-3/Chapter-3-Introduction.md)**
- **Previous Item(上一条目):[Item 13: Override clone judiciously(明智地覆盖 clone 方法)](/Chapter-3/Chapter-3-Item-13-Override-clone-judiciously.md)**
- **Next Item(下一条目):[Chapter 4 Introduction(章节介绍)](/Chapter-4/Chapter-4-Introduction.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(考虑以序列化代理代替序列化实例)