Skip to content

Commit

Permalink
在Item-2中添加了示例代码和说明;进一步移除单词释义
Browse files Browse the repository at this point in the history
  • Loading branch information
clxering committed Jul 29, 2020
1 parent e09cc5d commit 0ddf712
Show file tree
Hide file tree
Showing 8 changed files with 12 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Prior to Java 8, interfaces couldn’t have static methods. By convention, stati

**译注:原文 noninstantiable 应修改为 non-instantiable ,译为「不可实例化的」**

The Collections Framework API is much smaller than it would have been had it exported forty-five separate public classes, one for each convenience implementation. It is not just the bulk of the API that is reduced but the conceptual(abj.概念上的) weight: the number and difficulty of the concepts that programmers must master in order to use the API. The programmer knows that the returned object has precisely the API specified by its interface, so there is no need to read additional class documentation for the implementation class. Furthermore, using such a static factory method requires the client to refer to the returned object by interface rather than implementation class, which is generally good practice (Item 64).
The Collections Framework API is much smaller than it would have been had it exported forty-five separate public classes, one for each convenience implementation. It is not just the bulk of the API that is reduced but the conceptual weight: the number and difficulty of the concepts that programmers must master in order to use the API. The programmer knows that the returned object has precisely the API specified by its interface, so there is no need to read additional class documentation for the implementation class. Furthermore, using such a static factory method requires the client to refer to the returned object by interface rather than implementation class, which is generally good practice (Item 64).

Collections 框架 API 比它导出 45 个独立的公共类要小得多,每个公共类对应一个方便的实现。减少的不仅仅是 API 的数量,还有概念上的减少:程序员为了使用 API 必须掌握的概念的数量和难度。程序员知道返回的对象是由相关的接口精确地指定的,因此不需要为实现类阅读额外的类文档。此外,使用这种静态工厂方法需要客户端通过接口而不是实现类引用返回的对象,这通常是很好的做法([Item-64](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-9/Chapter-9-Item-64-Refer-to-objects-by-their-interfaces.md))。

Expand Down Expand Up @@ -88,7 +88,7 @@ An optional fourth component of a service provider framework is a service provid

服务提供者框架的第四个可选组件是服务提供者接口,它描述了产生服务接口实例的工厂对象。在没有服务提供者接口的情况下,必须以反射的方式实例化实现([Item-65](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-9/Chapter-9-Item-65-Prefer-interfaces-to-reflection.md))。在 JDBC 中,连接扮演服务接口 DriverManager 的角色。`DriverManager.registerDriver` 是提供商注册的 API,`DriverManager.getConnection` 是服务访问 API,驱动程序是服务提供者接口。

There are many variants of the service provider framework pattern. For example, the service access API can return a richer service interface to clients than the one furnished by providers. This is the Bridge pattern [Gamma95]. Dependency injection frameworks (Item 5) can be viewed as powerful service providers. Since Java 6, the platform includes a general-purpose service provider framework, java.util.ServiceLoader, so you needn’t, and generally shouldn’t, write your own (Item 59). JDBC doesn’t use ServiceLoader, as the former predates(vt.先于) the latter.
There are many variants of the service provider framework pattern. For example, the service access API can return a richer service interface to clients than the one furnished by providers. This is the Bridge pattern [Gamma95]. Dependency injection frameworks (Item 5) can be viewed as powerful service providers. Since Java 6, the platform includes a general-purpose service provider framework, java.util.ServiceLoader, so you needn’t, and generally shouldn’t, write your own (Item 59). JDBC doesn’t use ServiceLoader, as the former predates the latter.

服务提供者框架模式有许多变体。例如,服务访问 API 可以向客户端返回比提供者提供的更丰富的服务接口。这是桥接模式 [Gamma95]。依赖注入框架([Item-5](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-2/Chapter-2-Item-5-Prefer-dependency-injection-to-hardwiring-resources.md))可以看作是强大的服务提供者。由于是 Java 6,该平台包括一个通用服务提供者框架 `Java.util.ServiceLoader`,所以你不需要,通常也不应该自己写([Item-59](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-9/Chapter-9-Item-59-Know-and-use-the-libraries.md))。JDBC 不使用 ServiceLoader,因为前者比后者要早。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public class NutritionFacts {
使用案例改为:

```
NutritionFacts cocaCola = new EntityCreator.Init(Food.class)
NutritionFacts cocaCola = new EntityCreator.Init(NutritionFacts.class)
.setValue("servingSize",240)
.setValue("servings",8)
.setValue("calories",100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Elvis obj = sup.get();
obj.leaveTheBuilding();
```

To make a singleton class that uses either of these approaches serializable (Chapter 12), it is not sufficient merely to add implements Serializable to its declaration. To maintain(vt.维持) the singleton guarantee, declare all instance fields transient and provide a readResolve method (Item 89). Otherwise, each time a serialized instance is deserialized, a new instance will be created, leading,in the case of our example, to spurious Elvis sightings. To prevent this from happening, add this readResolve method to the Elvis class:
To make a singleton class that uses either of these approaches serializable (Chapter 12), it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, declare all instance fields transient and provide a readResolve method (Item 89). Otherwise, each time a serialized instance is deserialized, a new instance will be created, leading,in the case of our example, to spurious Elvis sightings. To prevent this from happening, add this readResolve method to the Elvis class:

要使单例类使用这两种方法中的任何一种(Chapter 12),仅仅在其声明中添加实现 serializable 是不够的。要维护单例保证,应声明所有实例字段为 transient,并提供 readResolve 方法([Item-89](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-12/Chapter-12-Item-89-For-instance-control-prefer-enum-types-to-readResolve.md))。否则,每次反序列化实例时,都会创建一个新实例,在我们的示例中,这会导致出现虚假的 Elvis。为了防止这种情况发生,将这个 readResolve 方法添加到 Elvis 类中:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ An added benefit of nulling out obsolete references is that if they are subseque

用 null 处理过时引用的另一个好处是,如果它们随后被错误地关联引用,程序将立即失败,出现 NullPointerException,而不是悄悄地做错误的事情。尽可能快地检测编程错误总是有益的。

When programmers are first stung by this problem, they may overcompensate(vt.给予…过度补偿) by nulling out every object reference as soon as the program is finished using it.This is neither necessary nor desirable; it clutters up the program unnecessarily.Nulling out object references should be the exception rather than the norm.The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope (Item 57).
When programmers are first stung by this problem, they may overcompensate by nulling out every object reference as soon as the program is finished using it.This is neither necessary nor desirable; it clutters up the program unnecessarily.Nulling out object references should be the exception rather than the norm.The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope (Item 57).

当程序员第一次被这个问题困扰时,他们可能会过度担心,一旦程序使用完它,他们就会取消所有对象引用。这既无必要也不可取;它不必要地搞乱了程序。清除对象引用应该是例外,而不是规范。消除过时引用的最佳方法是让包含引用的变量脱离作用域。如果你在最狭窄的范围内定义每个变量([Item-57](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-9/Chapter-9-Item-57-Minimize-the-scope-of-local-variables.md)),那么这种情况自然会发生。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ It may be hard to believe, but even good programmers got this wrong most of the

**译注:《Java Puzzlers》的中文译本为《Java 解惑》**

Even the correct code for closing resources with try-finally statements,as illustrated in the previous two code examples, has a subtle deficiency. The code in both the try block and the finally block is capable of throwing exceptions. For example, in the firstLineOfFile method, the call to readLine could throw an exception due to a failure in the underlying physical device, and the call to close could then fail for the same reason. Under these circumstances, the second exception completely obliterates(vt.抹去) the first one. There is no record of the first exception in the exception stack trace, which can greatly complicate debugging in real systems—usually it’s the first exception that you want to see in order to diagnose the problem. While it is possible to write code to suppress the second exception in favor of the first, virtually no one did because it’s just too verbose.
Even the correct code for closing resources with try-finally statements,as illustrated in the previous two code examples, has a subtle deficiency. The code in both the try block and the finally block is capable of throwing exceptions. For example, in the firstLineOfFile method, the call to readLine could throw an exception due to a failure in the underlying physical device, and the call to close could then fail for the same reason. Under these circumstances, the second exception completely obliterates the first one. There is no record of the first exception in the exception stack trace, which can greatly complicate debugging in real systems—usually it’s the first exception that you want to see in order to diagnose the problem. While it is possible to write code to suppress the second exception in favor of the first, virtually no one did because it’s just too verbose.

使用 try-finally 语句关闭资源的正确代码(如前两个代码示例所示)也有一个细微的缺陷。try 块和 finally 块中的代码都能够抛出异常。例如,在 firstLineOfFile 方法中,由于底层物理设备发生故障,对 readLine 的调用可能会抛出异常,而关闭的调用也可能出于同样的原因而失败。在这种情况下,第二个异常将完全覆盖第一个异常。异常堆栈跟踪中没有第一个异常的记录,这可能会使实际系统中的调试变得非常复杂(而这可能是希望出现的第一个异常,以便诊断问题)。虽然可以通过编写代码来抑制第二个异常而支持第一个异常,但实际上没有人这样做,因为它太过冗长。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Item 11: Always override hashCode when you override equals(当覆盖 equals 时,始终覆盖 hashCode)

**You must override hashCode in every class that overrides equals.** If you fail to do so, your class will violate(vt.违反) the general contract for hashCode, which will prevent it from functioning properly in collections such as HashMap and HashSet. Here is the contract, adapted from the Object specification :
**You must override hashCode in every class that overrides equals.** If you fail to do so, your class will violate the general contract for hashCode, which will prevent it from functioning properly in collections such as HashMap and HashSet. Here is the contract, adapted from the Object specification :

**在覆盖 equals 的类中,必须覆盖 hashCode。** 如果你没有这样做,你的类将违反 hashCode 的一般约定,这将阻止该类在 HashMap 和 HashSet 等集合中正常运行。以下是根据目标规范修改的约定:

Expand Down Expand Up @@ -45,7 +45,7 @@ It’s legal because it ensures that equal objects have the same hash code. It

它是合法的,因为它确保了相等的对象具有相同的 hash 代码。同时它也很糟糕,因为它使每个对象都有相同的 hash 代码。因此,每个对象都 hash 到同一个桶中, hash 表退化为链表。应以线性时间替代运行的程序。对于大型 hash 表,这是工作和不工作的区别。

A good hash function tends to produce unequal hash codes for unequal instances. This is exactly what is meant by the third part of the hashCode contract. Ideally, a hash function should distribute(vt.分配) any reasonable collection of unequal instances uniformly across all int values. Achieving this ideal can be difficult. Luckily it’s not too hard to achieve a fair approximation. Here is a simple recipe:
A good hash function tends to produce unequal hash codes for unequal instances. This is exactly what is meant by the third part of the hashCode contract. Ideally, a hash function should distribute any reasonable collection of unequal instances uniformly across all int values. Achieving this ideal can be difficult. Luckily it’s not too hard to achieve a fair approximation. Here is a simple recipe:

一个好的 hash 函数倾向于为不相等的实例生成不相等的 hash 代码。这正是 hashCode 约定的第三部分的含义。理想情况下, hash 函数应该在所有 int 值之间均匀分布所有不相等实例的合理集合。实现这个理想是很困难的。幸运的是,实现一个类似的并不太难。这里有一个简单的方式:

Expand Down Expand Up @@ -89,7 +89,7 @@ When you are finished writing the hashCode method, ask yourself whether equal in

当你完成了 hashCode 方法的编写之后,问问自己相同的实例是否具有相同的 hash 代码。编写单元测试来验证你的直觉(除非你使用 AutoValue 生成你的 equals 和 hashCode 方法,在这种情况下你可以安全地省略这些测试)。如果相同的实例有不相等的 hash 码,找出原因并修复问题。

You may exclude(vt.排除) derived fields from the hash code computation. In other words, you may ignore any field whose value can be computed from fields included in the computation. You must exclude any fields that are not used in equals comparisons, or you risk violating the second provision of the hashCode contract.
You may exclude derived fields from the hash code computation. In other words, you may ignore any field whose value can be computed from fields included in the computation. You must exclude any fields that are not used in equals comparisons, or you risk violating the second provision of the hashCode contract.

可以从 hash 代码计算中排除派生字段。换句话说,你可以忽略任何可以从计算中包含的字段计算其值的字段。你必须排除不用于对等比较的任何字段,否则你可能会违反 hashCode 约定的第二个条款。

Expand Down Expand Up @@ -162,7 +162,7 @@ This is not just a theoretical problem. Prior to Java 2, the String hash functio

这不仅仅是一个理论问题。在 Java 2 之前,字符串 hash 函数在字符串中,以第一个字符开始,最多使用 16 个字符。对于大量的分级名称集合(如 url),该函数完全显示了前面描述的病态行为。

**Don’t provide a detailed specification for the value returned by hashCode, so clients can’t reasonably depend on it; this gives you the flexibility to change it.** Many classes in the Java libraries, such as String and Integer, specify(vt.指定,详细说明) the exact value returned by their hashCode method as a function of the instance value. This is not a good idea but a mistake that we’re forced to live with: It impedes the ability to improve the hash function in future releases. If you leave the details unspecified and a flaw is found in the hash function or a better hash function is discovered, you can change it in a subsequent release.
**Don’t provide a detailed specification for the value returned by hashCode, so clients can’t reasonably depend on it; this gives you the flexibility to change it.** Many classes in the Java libraries, such as String and Integer, specify the exact value returned by their hashCode method as a function of the instance value. This is not a good idea but a mistake that we’re forced to live with: It impedes the ability to improve the hash function in future releases. If you leave the details unspecified and a flaw is found in the hash function or a better hash function is discovered, you can change it in a subsequent release.

**不要为 hashCode 返回的值提供详细的规范,这样客户端就不能合理地依赖它。这(也)给了你更改它的灵活性。** Java 库中的许多类,例如 String 和 Integer,都将 hashCode 方法返回的确切值指定为实例值的函数。这不是一个好主意,而是一个我们不得不面对的错误:它阻碍了在未来版本中改进 hash 函数的能力。如果你保留了未指定的细节,并且在 hash 函数中发现了缺陷,或者发现了更好的 hash 函数,那么你可以在后续版本中更改它。

Expand Down
Loading

0 comments on commit 0ddf712

Please sign in to comment.