From 0ddf71282241f571aa5255c1cc200295c21633f2 Mon Sep 17 00:00:00 2001 From: clxering Date: Wed, 29 Jul 2020 23:37:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8Item-2=E4=B8=AD=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E7=A4=BA=E4=BE=8B=E4=BB=A3=E7=A0=81=E5=92=8C=E8=AF=B4?= =?UTF-8?q?=E6=98=8E;=E8=BF=9B=E4=B8=80=E6=AD=A5=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=8D=95=E8=AF=8D=E9=87=8A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ider-static-factory-methods-instead-of-constructors.md | 4 ++-- ...builder-when-faced-with-many-constructor-parameters.md | 2 +- ...property-with-a-private-constructor-or-an-enum-type.md | 2 +- ...apter-2-Item-7-Eliminate-obsolete-object-references.md | 2 +- ...r-2-Item-9-Prefer-try-with-resources-to-try-finally.md | 2 +- ...1-Always-override-hashCode-when-you-override-equals.md | 8 ++++---- ...5-Minimize-the-accessibility-of-classes-and-members.md | 2 +- .../Chapter-5-Item-27-Eliminate-unchecked-warnings.md | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Chapter-2/Chapter-2-Item-1-Consider-static-factory-methods-instead-of-constructors.md b/Chapter-2/Chapter-2-Item-1-Consider-static-factory-methods-instead-of-constructors.md index 1d2c6c6..2bb50ed 100644 --- a/Chapter-2/Chapter-2-Item-1-Consider-static-factory-methods-instead-of-constructors.md +++ b/Chapter-2/Chapter-2-Item-1-Consider-static-factory-methods-instead-of-constructors.md @@ -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))。 @@ -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,因为前者比后者要早。 diff --git a/Chapter-2/Chapter-2-Item-2-Consider-a-builder-when-faced-with-many-constructor-parameters.md b/Chapter-2/Chapter-2-Item-2-Consider-a-builder-when-faced-with-many-constructor-parameters.md index fdcd07c..d42da8c 100644 --- a/Chapter-2/Chapter-2-Item-2-Consider-a-builder-when-faced-with-many-constructor-parameters.md +++ b/Chapter-2/Chapter-2-Item-2-Consider-a-builder-when-faced-with-many-constructor-parameters.md @@ -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) diff --git a/Chapter-2/Chapter-2-Item-3-Enforce-the-singleton-property-with-a-private-constructor-or-an-enum-type.md b/Chapter-2/Chapter-2-Item-3-Enforce-the-singleton-property-with-a-private-constructor-or-an-enum-type.md index ee83806..0a9e3ea 100644 --- a/Chapter-2/Chapter-2-Item-3-Enforce-the-singleton-property-with-a-private-constructor-or-an-enum-type.md +++ b/Chapter-2/Chapter-2-Item-3-Enforce-the-singleton-property-with-a-private-constructor-or-an-enum-type.md @@ -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 类中: diff --git a/Chapter-2/Chapter-2-Item-7-Eliminate-obsolete-object-references.md b/Chapter-2/Chapter-2-Item-7-Eliminate-obsolete-object-references.md index 1dee173..bd7f1bd 100644 --- a/Chapter-2/Chapter-2-Item-7-Eliminate-obsolete-object-references.md +++ b/Chapter-2/Chapter-2-Item-7-Eliminate-obsolete-object-references.md @@ -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)),那么这种情况自然会发生。 diff --git a/Chapter-2/Chapter-2-Item-9-Prefer-try-with-resources-to-try-finally.md b/Chapter-2/Chapter-2-Item-9-Prefer-try-with-resources-to-try-finally.md index c5fe602..31f39b6 100644 --- a/Chapter-2/Chapter-2-Item-9-Prefer-try-with-resources-to-try-finally.md +++ b/Chapter-2/Chapter-2-Item-9-Prefer-try-with-resources-to-try-finally.md @@ -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 的调用可能会抛出异常,而关闭的调用也可能出于同样的原因而失败。在这种情况下,第二个异常将完全覆盖第一个异常。异常堆栈跟踪中没有第一个异常的记录,这可能会使实际系统中的调试变得非常复杂(而这可能是希望出现的第一个异常,以便诊断问题)。虽然可以通过编写代码来抑制第二个异常而支持第一个异常,但实际上没有人这样做,因为它太过冗长。 diff --git a/Chapter-3/Chapter-3-Item-11-Always-override-hashCode-when-you-override-equals.md b/Chapter-3/Chapter-3-Item-11-Always-override-hashCode-when-you-override-equals.md index a5b7425..8e66e38 100644 --- a/Chapter-3/Chapter-3-Item-11-Always-override-hashCode-when-you-override-equals.md +++ b/Chapter-3/Chapter-3-Item-11-Always-override-hashCode-when-you-override-equals.md @@ -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 等集合中正常运行。以下是根据目标规范修改的约定: @@ -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 值之间均匀分布所有不相等实例的合理集合。实现这个理想是很困难的。幸运的是,实现一个类似的并不太难。这里有一个简单的方式: @@ -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 约定的第二个条款。 @@ -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 函数,那么你可以在后续版本中更改它。 diff --git a/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md b/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md index 2129df2..8e0d0b0 100644 --- a/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md +++ b/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md @@ -58,7 +58,7 @@ There is a key rule that restricts your ability to reduce the accessibility of m 有一个关键规则限制了你减少方法可访问性的能力。如果一个方法覆盖了超类方法,那么它在子类中的访问级别就不能比在超类 [JLS, 8.4.8.3] 中更严格。这对于确保子类的实例在超类的实例可用的任何地方都同样可用是必要的(Liskov 替换原则,请参阅 [Item-15](https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/master/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md))。如果违反此规则,编译器将在尝试编译子类时生成错误消息。这个规则的一个特例是,如果一个类实现了一个接口,那么该接口中的所有类方法都必须在类中声明为 public。 -To facilitate(vt. 促进;帮助;使容易) testing your code, you may be tempted to make a class, interface,or member more accessible than otherwise necessary. This is fine up to a point. It is acceptable to make a private member of a public class package-private in order to test it, but it is not acceptable to raise the accessibility any higher. In other words, it is not acceptable to make a class, interface, or member a part of a package’s exported API to facilitate testing. Luckily, it isn’t necessary either because tests can be made to run as part of the package being tested, thus gaining access to its package-private elements. +To facilitate testing your code, you may be tempted to make a class, interface,or member more accessible than otherwise necessary. This is fine up to a point. It is acceptable to make a private member of a public class package-private in order to test it, but it is not acceptable to raise the accessibility any higher. In other words, it is not acceptable to make a class, interface, or member a part of a package’s exported API to facilitate testing. Luckily, it isn’t necessary either because tests can be made to run as part of the package being tested, thus gaining access to its package-private elements. 为了便于测试代码,你可能会倾向于使类、接口或成员更容易访问。这在一定程度上是好的。为了测试一个公共类包的私有成员是可以接受的,但是提高可访问性是不可接受的。换句话说,将类、接口或成员作为包导出 API 的一部分以方便测试是不可接受的。幸运的是,也没有必要这样做,因为测试可以作为包的一部分运行,从而获得对包私有元素的访问权。 diff --git a/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md b/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md index 6236501..3332fef 100644 --- a/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md +++ b/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md @@ -25,7 +25,7 @@ Set exaltation = new HashSet(); found: HashSet ``` -You can then make the indicated correction, causing the warning to disappear. Note that you don’t actually have to specify the type parameter, merely to indicate(vt. 表明;指出;预示;象征) that it’s present with the diamond operator (<>), introduced in Java 7. The compiler will then infer the correct actual type parameter (in this case, Lark): +You can then make the indicated correction, causing the warning to disappear. Note that you don’t actually have to specify the type parameter, merely to indicate that it’s present with the diamond operator (<>), introduced in Java 7. The compiler will then infer the correct actual type parameter (in this case, Lark): 你可以在指定位置进行更正,使警告消失。注意,你实际上不必指定类型参数,只需给出由 Java 7 中引入的 diamond 操作符(<>)。然后编译器将推断出正确的实际类型参数(在本例中为 Lark):