From 09d236bd09105cf92fdc31e7856e023eef2fb389 Mon Sep 17 00:00:00 2001 From: l00263786 Date: Wed, 22 Jan 2020 14:21:53 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" index e749cf5..d9e070e 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" @@ -34,7 +34,7 @@ public static Boolean valueOf(boolean b) {   **静态工厂方法的第四个优点是,静态工厂方法所返回的对象的类可以随着每次调用而变化,这取决于静态工厂方法的参数值。** 只要返回的类型是声明的类的子类都是允许的。返回对象的类也可能随着发行版本的不同而不同。 -  在`EnumSet`类(第 36 项)中有非公有的构造方法,只有静态工厂方法。在 OpenJDK 实现中的,它们返回两个子类之一的实例,具体取决于基础枚举类型的大小: 如果它有 64 个或更少的元素,就像大多数枚举类型所做的那样,静态工厂返回一个`RegularEnumSet`实例, 它由单个`long`的支持;如果枚举类型有 65 个或更多元素,则工厂将返回一个由长数组支持的`JumboEnumSet`实例。 +  在`EnumSet`类(第 36 项)中没有公有的构造方法,只有静态工厂方法。在 OpenJDK 实现中的,它们返回两个子类之一的实例,具体取决于基础枚举类型的大小: 如果它有 64 个或更少的元素,就像大多数枚举类型所做的那样,静态工厂返回一个`RegularEnumSet`实例, 它由单个`long`的支持;如果枚举类型有 65 个或更多元素,则工厂将返回一个由长数组支持的`JumboEnumSet`实例。   这两个实现类的存在对于客户端是不可见的。 如果 RegularEnumSet 不再为小枚举类型提供性能优势可以从未来版本中删除,没有任何不良影响。 同样,未来如果证明有利于性能,则可以添加`EnumSet`的第三或第四个实现。客户即不知道也不关心他们从工厂中获取的对象的类型,他们只关心它是`EnumSet`的一些子类。 -- Gitee From 64be31819fab048241b149fa574331976500e3d8 Mon Sep 17 00:00:00 2001 From: l00263786 Date: Wed, 22 Jan 2020 15:53:54 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E4=B8=BA=E8=87=AA=E5=B7=B1=E7=9A=84=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 202 +++++++++--------- ...04\351\200\240\345\207\275\346\225\260.md" | 2 +- ...50\346\236\204\345\273\272\345\231\250.md" | 4 +- ...4\226Singleton\345\261\236\346\200\247.md" | 4 +- ...26\347\232\204\350\203\275\345\212\233.md" | 4 +- ...35\350\265\226\346\263\250\345\205\245.md" | 4 +- ...01\347\232\204\345\257\271\350\261\241.md" | 4 +- ...41\347\232\204\345\274\225\347\224\250.md" | 4 +- ...05\347\251\272\346\226\271\346\263\225.md" | 4 +- ...230\345\205\210\344\272\216try-finally.md" | 4 +- ...32\347\224\250\347\272\246\345\256\232.md" | 4 +- ...06\231hashCode\346\226\271\346\263\225.md" | 4 +- ...06\231toString\346\226\271\346\263\225.md" | 4 +- ...5\206\231clone\346\226\271\346\263\225.md" | 4 +- ...\260Comparable\346\216\245\345\217\243.md" | 4 +- ...47\346\234\200\345\260\217\345\214\226.md" | 4 +- ...36\345\205\254\346\234\211\345\237\237.md" | 4 +- ...47\346\234\200\345\260\217\345\214\226.md" | 4 +- ...10\344\272\216\347\273\247\346\211\277.md" | 4 +- ...01\346\255\242\347\273\247\346\211\277.md" | 4 +- ...16\346\212\275\350\261\241\347\261\273.md" | 4 +- ...76\350\256\241\346\216\245\345\217\243.md" | 4 +- ...32\344\271\211\347\261\273\345\236\213.md" | 4 +- ...16\346\240\207\347\255\276\347\261\273.md" | 4 +- ...01\346\210\220\345\221\230\347\261\273.md" | 4 +- ...52\351\241\266\347\272\247\347\261\273.md" | 4 +- ...37\346\200\201\347\261\273\345\236\213.md" | 4 +- ...27\346\243\200\350\255\246\345\221\212.md" | 4 +- ...10\344\272\216\346\225\260\347\273\204.md" | 4 +- ...03\350\231\221\346\263\233\345\236\213.md" | 4 +- ...33\345\236\213\346\226\271\346\263\225.md" | 4 +- ...04\347\201\265\346\264\273\346\200\247.md" | 4 +- ...57\345\217\230\345\217\202\346\225\260.md" | 4 +- ...02\346\236\204\345\256\271\345\231\250.md" | 4 +- ...346\233\277int\345\270\270\351\207\217.md" | 4 +- ...43\346\233\277\345\272\217\346\225\260.md" | 4 +- ...43\346\233\277\344\275\215\345\237\237.md" | 4 +- ...17\346\225\260\347\264\242\345\274\225.md" | 4 +- ...25\347\232\204\346\236\232\344\270\276.md" | 4 +- ...75\345\220\215\346\250\241\345\274\217.md" | 4 +- ...224\250Overide\346\263\250\350\247\243.md" | 4 +- ...32\344\271\211\347\261\273\345\236\213.md" | 4 +- ...16\345\214\277\345\220\215\347\261\273.md" | 4 +- ...\274\230\345\205\210\344\272\216Lambda.md" | 4 +- ...75\346\225\260\346\216\245\345\217\243.md" | 4 +- ...\205\216\344\275\277\347\224\250Stream.md" | 4 +- ...50\347\232\204\345\207\275\346\225\260.md" | 4 +- ...24\345\233\236\347\261\273\345\236\213.md" | 4 +- ...\224\250Stream\345\271\266\350\241\214.md" | 4 +- ...04\346\234\211\346\225\210\346\200\247.md" | 4 +- ...44\346\200\247\346\213\267\350\264\235.md" | 4 +- ...71\346\263\225\347\255\276\345\220\215.md" | 4 +- ...16\347\224\250\351\207\215\350\275\275.md" | 4 +- ...57\345\217\230\345\217\202\346\225\260.md" | 4 +- ...50\200\214\344\270\215\346\230\257null.md" | 4 +- ...05\216\350\277\224\345\233\236optional.md" | 4 +- ...07\346\241\243\346\263\250\351\207\212.md" | 4 +- ...37\346\234\200\345\260\217\345\214\226.md" | 4 +- ...347\232\204for\345\276\252\347\216\257.md" | 4 +- ...77\347\224\250\347\261\273\345\272\223.md" | 4 +- ...277\347\224\250float\345\222\214double.md" | 4 +- ...72\346\234\254\347\261\273\345\236\213.md" | 4 +- ...50\345\255\227\347\254\246\344\270\262.md" | 4 +- ...45\347\232\204\346\200\247\350\203\275.md" | 4 +- ...25\347\224\250\345\257\271\350\261\241.md" | 4 +- ...15\345\260\204\346\234\272\345\210\266.md" | 4 +- ...54\345\234\260\346\226\271\346\263\225.md" | 4 +- ...33\350\241\214\344\274\230\345\214\226.md" | 4 +- ...75\345\220\215\346\203\257\344\276\213.md" | 4 +- ...77\347\224\250\345\274\202\345\270\270.md" | 4 +- ...14\346\227\266\345\274\202\345\270\270.md" | 4 +- ...27\346\243\200\345\274\202\345\270\270.md" | 4 +- ...06\347\232\204\345\274\202\345\270\270.md" | 4 +- ...24\347\232\204\345\274\202\345\270\270.md" | 4 +- ...72\347\253\213\346\226\207\346\241\243.md" | 4 +- ...61\350\264\245\344\277\241\346\201\257.md" | 4 +- ...01\345\216\237\345\255\220\346\200\247.md" | 4 +- ...75\347\225\245\345\274\202\345\270\270.md" | 4 +- ...57\345\217\230\346\225\260\346\215\256.md" | 4 +- ...07\345\272\246\345\220\214\346\255\245.md" | 4 +- ...10\344\272\216\347\272\277\347\250\213.md" | 4 +- ...\210\344\272\216wait\345\222\214notify.md" | 4 +- ...04\346\226\207\346\241\243\345\214\226.md" | 4 +- ...37\345\210\235\345\247\213\345\214\226.md" | 4 +- ...13\350\260\203\345\272\246\345\231\250.md" | 4 +- ...va\345\272\217\345\210\227\345\214\226.md" | 4 +- ...60Serializable\346\216\245\345\217\243.md" | 4 +- ...27\345\214\226\345\275\242\345\274\217.md" | 4 +- ...\231readObject\346\226\271\346\263\225.md" | 4 +- ...230\345\205\210\344\272\216readResolve.md" | 4 +- ...27\345\214\226\345\256\236\344\276\213.md" | 2 +- 91 files changed, 279 insertions(+), 279 deletions(-) diff --git a/README.md b/README.md index b059462..9266a35 100644 --- a/README.md +++ b/README.md @@ -26,172 +26,172 @@ Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的 --- -### [第二章 创建和销毁对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象) +### [第二章 创建和销毁对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象)   本章涉及创建和销毁对象,包括何时以及如何创建它们,何时以及如何避免创建它们,如何确保它们被及时销毁,以及如何管理在销毁之前必须进行的清理操作。 -> - [第 1 项:考虑静态工厂方法而不是构造函数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第1项:考虑静态工厂方法而不是构造函数.md) -> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) -> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) -> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) -> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) -> - [第 6 项:避免创建不必要的对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) -> - [第 7 项:消除过期的对象引用](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) -> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) -> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) +> - [第 1 项:考虑静态工厂方法而不是构造函数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第1项:考虑静态工厂方法而不是构造函数.md) +> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) +> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) +> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) +> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) +> - [第 6 项:避免创建不必要的对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) +> - [第 7 项:消除过期的对象引用](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) +> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) +> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) --- -### [第三章 对于所有对象都通用的方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法) +### [第三章 对于所有对象都通用的方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法)   尽管 Object 是一个具体类,但是设计它主要是为了扩展。它所有的非 final 方法(equals、hashCode、toString、clone 和 finalize)都有明确的通用约定(general contracts),因为它们被设计成是要被重写(override)的。任何一个类,它在覆盖这些方法的时候,都有责任遵守这些通用约定;如果做不到这一点,其他依赖于这些约定的类(例如 HashMap 和 HashSet)就无法结合该类一起正常运作。   本章将讲述何时以及如何覆盖这些非 final 的 Object 方法。本章不再讨论 finalize 方法,因为第 7 项已经讨论过这个方法了。而 Comparable.compareTo 虽然不是 Object 方法,但是本章也对它进行讨论,因为它具有类似的特征。 -> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) -> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) -> - [第 12 项:始终重写 toString 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) -> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) -> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) +> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) +> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) +> - [第 12 项:始终重写 toString 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) +> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) +> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) --- -### [第四章 类和接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口) +### [第四章 类和接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口)   类和接口是 Java 程序设计语言的核心,他们也是 Java 语言的基本抽象单元。Java 语言提供了许多强大的基本元素,供程序猿来设计类和接口。本章包含的一些指南可以帮助你充分利用这些元素,以便让你编写的类和接口可用、健壮且灵活。 -> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) -> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) -> - [第 17 项:使可变性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) -> - [第 18 项:复合优先于继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) -> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) -> - [第 20 项:接口优于抽象类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) -> - [第 21 项:为后代设计接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) -> - [第 22 项:接口只用于定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) -> - [第 23 项:类层次优于标签类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) -> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) -> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) +> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) +> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) +> - [第 17 项:使可变性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) +> - [第 18 项:复合优先于继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) +> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) +> - [第 20 项:接口优于抽象类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) +> - [第 21 项:为后代设计接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) +> - [第 22 项:接口只用于定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) +> - [第 23 项:类层次优于标签类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) +> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) +> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) --- -### [第五章 泛型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型) +### [第五章 泛型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型)   Java 1.5 发行版本中增加了泛型(Generic)。在没有泛型之前,从集合中读取到的每一个对象都必须进行转换。如果有人不小心插入了类型错误的对象,在运行时进行转换处理就会出错。有个泛型,可以告诉编译器每个集合中接收哪些对象类型。编译器自动地为你的插入进行转化,并在编译时告知是否插入了类型错误的对象。这样可以使程序既更加安全,也更加清楚,但是这些好处(不仅仅针对集合)是需要付出代价的。本章将告诉您如何最大化利益并最大限度地减少并发症【使用泛型带来的坏处】(complications)。 -> - [第 26 项:请不要使用原生态类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) -> - [第 27 项:消除非受检的警告](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) -> - [第 28 项:列表优于数组](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) -> - [第 29 项:优先考虑泛型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) -> - [第 30 项:优先考虑泛型方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) -> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) -> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) -> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) +> - [第 26 项:请不要使用原生态类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) +> - [第 27 项:消除非受检的警告](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) +> - [第 28 项:列表优于数组](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) +> - [第 29 项:优先考虑泛型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) +> - [第 30 项:优先考虑泛型方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) +> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) +> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) +> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) --- -### [第六章 枚举和注解](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解) +### [第六章 枚举和注解](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解)   Java 支持两种特殊用途的引用类型:一种称为枚举(enum type)类型,以及一种称为注解类型(annotation type)的接口。本章讨论使用这些类型系列的最佳实践。 -> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) -> - [第 35 项:用实例域代替序数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) -> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) -> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) -> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) -> - [第 39 项:注解优先于命名模式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) -> - [第 40 项:坚持使用 Override 注解](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) -> - [第 41 项:用标记接口定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) +> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) +> - [第 35 项:用实例域代替序数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) +> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) +> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) +> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) +> - [第 39 项:注解优先于命名模式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) +> - [第 40 项:坚持使用 Override 注解](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) +> - [第 41 项:用标记接口定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) --- -### [第七章 Lambda 和 Stream](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream) +### [第七章 Lambda 和 Stream](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream)   在 Java 8 中,添加了函数接口,lambda 和方法引用,以便更容易地创建函数对象。在这些语法(language)更改的同时添加进了流 API,以便为处理数据元素序列提供支持的库。在本章中,我们将讨论如何充分利用这些工具。 -> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) -> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) -> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) -> - [第 45 项:谨慎使用 Stream](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) -> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) -> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) -> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) +> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) +> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) +> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) +> - [第 45 项:谨慎使用 Stream](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) +> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) +> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) +> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) --- -### [第八章 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法) +### [第八章 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法)   本章讨论了方法设计的几个方面:如何处理参数和返回值,如何设计方法签名以及如何为方法编写文档。本章中的大部分内容适用于构造函数和方法。与第 4 章一样,本章重点介绍可用性,健壮性和灵活性。 -> - [第 49 项:检查参数的有效性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) -> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) -> - [第 51 项:谨慎设计方法签名](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) -> - [第 52 项:慎用重载](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) -> - [第 53 项:慎用可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) -> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) -> - [第 55 项:谨慎返回 optinal](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) -> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) +> - [第 49 项:检查参数的有效性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) +> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) +> - [第 51 项:谨慎设计方法签名](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) +> - [第 52 项:慎用重载](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) +> - [第 53 项:慎用可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) +> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) +> - [第 55 项:谨慎返回 optinal](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) +> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) --- -### [第九章 通用编程](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/) +### [第九章 通用编程](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/)   本章主要讨论 Java 语言的具体细节,讨论了局部变量、控制结构、类库、数据类型,以及两种不是由语言本身提供的机制(reflection 和 native method,反射机制和本地方法)。最后讨论了优化和命名惯例。 -> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) -> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) -> - [第 59 项:了解和使用类库](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) -> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) -> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) -> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) -> - [第 63 项:了解字符串连接的性能](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) -> - [第 64 项:通过接口引用对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) -> - [第 65 项:接口优先于反射机制](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) -> - [第 66 项:谨慎地使用本地方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) -> - [第 67 项:谨慎地进行优化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) -> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) +> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) +> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) +> - [第 59 项:了解和使用类库](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) +> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) +> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) +> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) +> - [第 63 项:了解字符串连接的性能](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) +> - [第 64 项:通过接口引用对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) +> - [第 65 项:接口优先于反射机制](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) +> - [第 66 项:谨慎地使用本地方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) +> - [第 67 项:谨慎地进行优化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) +> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) --- -### [第十章 异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常) +### [第十章 异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常)   在最通常情况下,异常可以提高程序的可读性,可靠性和可维护性。如果使用不当,可能会产生相反的效果。本章提供有效使用异常的指南。 -> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) -> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) -> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) -> - [第 72 项:优先使用标准的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) -> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) -> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) -> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) -> - [第 76 项:努力使失败保持原子性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) -> - [第 77 项:不要忽略异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) +> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) +> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) +> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) +> - [第 72 项:优先使用标准的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) +> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) +> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) +> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) +> - [第 76 项:努力使失败保持原子性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) +> - [第 77 项:不要忽略异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) --- -### [第十一章 并发](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发) +### [第十一章 并发](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发)   线程(THREADS)机制允许同时进行多个活动。并发编程要比单线程编程要困难得多,因为有很多东西可能出错,也很难重现失败。你无法避免并发。它本来就存在 Java 平台中了,如果你要从多核处理器中获得更好的性能,并发也是一个必要条件,这些现在都是十分普遍的了。本章阐述的建议可以帮助你编写出清晰、正确、文档组织良好的并发程序。 -> - [第 78 项:同步访问共享的可变数据](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) -> - [第 79 项:避免过度同步](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) -> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) -> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) -> - [第 82 项:线程安全性的文档化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) -> - [第 83 项:慎用延迟初始化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) -> - [第 84 项:不要依赖于线程调度器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) +> - [第 78 项:同步访问共享的可变数据](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) +> - [第 79 项:避免过度同步](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) +> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) +> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) +> - [第 82 项:线程安全性的文档化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) +> - [第 83 项:慎用延迟初始化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) +> - [第 84 项:不要依赖于线程调度器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) --- -### [第十二章 序列化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化) +### [第十二章 序列化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化)   本章关注*对象序列化(object serialization)* ,它是一个 Java 的框架,用来将对象编码为字节流(_序列化(serializing)_),并从其编码中重构对象(_反序列化(deserializing)_)。一旦对象被序列化,其编码可以从一个 VM 发送到另一个 VM 或存储在磁盘上以便以后反序列化。本章重点介绍如何将序列化的危险最小化。 -> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) -> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) -> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) -> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) -> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) -> - [第 90 项:考虑用序列化代理代替序列化实例](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第90项:考虑用序列化代理代替序列化实例.md) +> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) +> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) +> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) +> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) +> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) +> - [第 90 项:考虑用序列化代理代替序列化实例](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第90项:考虑用序列化代理代替序列化实例.md) --- diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" index d9e070e..d2560ba 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" @@ -61,4 +61,4 @@ public static Boolean valueOf(boolean b) {   总之,静态工厂方法和公共构造函数都有它们的用途,理解它们的相对优点是值得的。 通常静态工厂是优选的,不要在第一反应就是使用构造函数,应当先考虑使用静态工厂方法。 -> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) +> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" index a2069f6..029676c 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" @@ -255,5 +255,5 @@ Calzone calzone = new Calzone.Builder().addTopping(HAM).sauceInside().build();   简而言之,如果类的构造器或者静态工厂方法中具有多个参数,设计这种类时,Builder 模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用 Builder 模式的客户端代码更易于阅读和编写,构建器也比 JavaBean 更加安全。 -> - [第 1 项:考虑静态工厂方法而不是构造函数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第1项:考虑静态工厂方法而不是构造函数.md) -> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) +> - [第 1 项:考虑静态工厂方法而不是构造函数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第1项:考虑静态工厂方法而不是构造函数.md) +> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2543\351\241\271\357\274\232\347\224\250\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\346\210\226\350\200\205\346\236\232\344\270\276\347\261\273\345\236\213\345\274\272\345\214\226Singleton\345\261\236\346\200\247.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2543\351\241\271\357\274\232\347\224\250\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\346\210\226\350\200\205\346\236\232\344\270\276\347\261\273\345\236\213\345\274\272\345\214\226Singleton\345\261\236\346\200\247.md" index c0b08c2..eedf653 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2543\351\241\271\357\274\232\347\224\250\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\346\210\226\350\200\205\346\236\232\344\270\276\347\261\273\345\236\213\345\274\272\345\214\226Singleton\345\261\236\346\200\247.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2543\351\241\271\357\274\232\347\224\250\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\346\210\226\350\200\205\346\236\232\344\270\276\347\261\273\345\236\213\345\274\272\345\214\226Singleton\345\261\236\346\200\247.md" @@ -56,5 +56,5 @@ public enum Elvis {   这种方法类似于公共领域方法,但它更简洁,免费提供序列化机制,并提供了对多个实例化的铁定保证,即使面对复杂的序列化或反射攻击。这种方法可能会有点不自然,但单元素枚举类型通常是实现单例的最佳方法。请注意,如果你的单例必须扩展`Enum`以外的超类,则不能使用此方法(尽管你可以声明枚举来实现接口)。 -> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) -> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) +> - [第 2 项:当面临多个参数的构造器时考虑使用构建器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第2项:当面临多个参数的构造器时考虑使用构建器.md) +> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2544\351\241\271\357\274\232\351\200\232\350\277\207\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\345\274\272\345\214\226\344\270\215\345\217\257\345\256\236\344\276\213\345\214\226\347\232\204\350\203\275\345\212\233.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2544\351\241\271\357\274\232\351\200\232\350\277\207\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\345\274\272\345\214\226\344\270\215\345\217\257\345\256\236\344\276\213\345\214\226\347\232\204\350\203\275\345\212\233.md" index 0c6e738..b65af9f 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2544\351\241\271\357\274\232\351\200\232\350\277\207\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\345\274\272\345\214\226\344\270\215\345\217\257\345\256\236\344\276\213\345\214\226\347\232\204\350\203\275\345\212\233.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2544\351\241\271\357\274\232\351\200\232\350\277\207\347\247\201\346\234\211\346\236\204\351\200\240\345\231\250\345\274\272\345\214\226\344\270\215\345\217\257\345\256\236\344\276\213\345\214\226\347\232\204\350\203\275\345\212\233.md" @@ -21,5 +21,5 @@ public class UtilityClass {   这种习惯用法也有副作用,它使得一个类不能拥有子类。因为子类的所有构造函数都必须显示或者隐式地调用父类的构造函数,在这种情形下,子类就没有可访问的父类构造器可用了。 -> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) -> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) +> - [第 3 项:用私有构造器或者枚举类型强化 Singleton 属性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第3项:用私有构造器或者枚举类型强化Singleton属性.md) +> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" index 2cc6063..96bc75c 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" @@ -55,5 +55,5 @@ Mosaic create(Supplier tileFactory) { ... }   总之,如果有一个类依赖一个或多个底层资源的类,并且底层资源类影响了类的行为,不要使用单例或静态实用程序类来实现它,并且不要让类直接创建这些资源(do not use a singleton or static utility class to implement a class that depends on one or more underlying resources whose behavior affects that of the class)。相反,将资源或工厂传递给构造函数(或静态工厂或构建器)。这种做法称为依赖注入,将极大地增强类的灵活性,可重用性和可测试性。 -> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) -> - [第 6 项:避免创建不必要的对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) +> - [第 4 项:通过私有构造器强化不可实例化的能力](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第4项:通过私有构造器强化不可实例化的能力.md) +> - [第 6 项:避免创建不必要的对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" index b488fc4..4d6fdf6 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" @@ -74,5 +74,5 @@ private static long sum() {   与本项对应的是第 50 项的“保护性拷贝”的内容。该项说得是:你应该重用已经存在的对象,而不是去创建一个新的对象。然而第 50 项说的是:你应该创建一个新的对象而不是重用一个已经存在的对象。注意,在提倡使用保护性拷贝的时候,因重用对象而付出的代价要远远大于因创建重复对象而付出的代价。必要时如果没能实施保护性拷贝,将会导致潜在的错误和安全漏洞,而不必要地创建对象则只会影响程序的风格和性能。 -> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) -> - [第 7 项:消除过期的对象引用](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) +> - [第 5 项:优先考虑依赖注入来引用资源](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第5项:固定资源首选使用依赖注入.md) +> - [第 7 项:消除过期的对象引用](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index 98c33f2..16ae907 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -67,5 +67,5 @@ public Object pop() {   由于内存泄漏通常不会表现出明显的失败迹象,所以他们可以在一个系统中存在很多年。往往只有通过仔细检查代码,或者借助于 Heap 剖析工具(Heap Profiler)才能发现内存泄漏问题。因此,如果能在内存泄漏发生之前就知道如何预测此类问题,并阻止它们发生,那是最好不过的了。 -> - [第 6 项:避免创建不必要的对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) -> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) \ No newline at end of file +> - [第 6 项:避免创建不必要的对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第6项:避免创建不需要的对象.md) +> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) \ No newline at end of file diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" index e98776b..edccb49 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" @@ -90,5 +90,5 @@ public class Teenager {   总之,除了作为安全网或终止非关键的本机资源之外,不要使用清理方法,也不要使用 Java 9 之前的版本(终结方法)。即使这样,也要注意不确定性和影响性能导致的后果(Even then, beware the indeterminacy and performance consequences)。 -> - [第 7 项:消除过期的对象引用](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) -> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) +> - [第 7 项:消除过期的对象引用](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第7项:清除过期对象的引用.md) +> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" index d4936d3..c31d97e 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" @@ -87,5 +87,5 @@ static String firstLineOfFile(String path, String defaultVal) {   这里经验教训是很明确的(The lesson is clear):在处理必须关闭的资源时,相比于 try-finally,始终优先使用 try-with-resources。 生成的代码更短更清晰,它生成的异常更有用。 try-with-resources 语句可以在使用必须关闭的资源的同同时轻松编写正确的代码,使用 try-finally 几乎是不可能的。 -> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) -> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) +> - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) +> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" index 81040d7..d2e6cf6 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" @@ -335,5 +335,5 @@ public boolean equals(MyClass o) {   总之,不要重写 equals 方法,除非您不得不这么做:在许多情况下,从 Object 继承的实现完全符合您的要求。 如果你确实重写了 equals,请确保比较所有类的关键字段,并使用之前提到的五个诀窍对它进行测试(If you do override equals, make sure to compare all of the class’s significant fields and to compare them in a manner that preserves all five provisions of the equals contract)。 -> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) -> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) +> - [第 9 项:try-with-resources 优先于 try-finally](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第9项:try-with-resources优先于try-finally.md) +> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" index fe892ea..f65b357 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" @@ -106,5 +106,5 @@ private int hashCode; // Automatically initialized to 0   总之,每次覆盖 equals 时都必须覆盖 hashCode,否则程序将无法正常运行。 您的 hashCode 方法必须遵守 Object 中指定的规定,并且必须合理地将不相等的哈希代码分配给不相等的实例。如果觉得有点单调乏味,就使用第 51 页【原书本】的方式,这很容易实现。如第 10 项所述,AutoValue 框架提供了手动编写 equals 和 hashCode 方法的详细替代方案,IDE 也提供了一些此功能。 -> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) -> - [第 12 项:始终重写 toString 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) +> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) +> - [第 12 项:始终重写 toString 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" index ad5b786..c5a8a76 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" @@ -65,5 +65,5 @@ Assertion failure: expected {abc, 123}, but was {abc, 123}.   回顾一下,在你编写的每个可实例化的类中重写 Object 的 toString 实现,除非超类已经这样做了。 它使类的使用更加愉快,并有助于调试。toString 方法应该以美学上令人愉悦的格式返回对象的简明有用的描述(The toString method should return a concise, useful description of the object, in an aesthetically pleasing format)。 -> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) -> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) +> - [第 11 项:当重写 equals 方法时总要重写 hashCode 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第11项:当重写equals方法时总要重写hashCode方法.md) +> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25413\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\351\207\215\345\206\231clone\346\226\271\346\263\225.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25413\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\351\207\215\345\206\231clone\346\226\271\346\263\225.md" index 311e0de..89fe82b 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25413\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\351\207\215\345\206\231clone\346\226\271\346\263\225.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25413\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\351\207\215\345\206\231clone\346\226\271\346\263\225.md" @@ -209,5 +209,5 @@ public static Yum newInstance(Yum yum) { ... };   既然 Cloneable 具有上述那么多问题,新的接口就不应该对它进行扩展,而且新的可扩展的类也不应该实现它。虽然实现 Cloneable 接口对 final 类的危害较小,但应将其视为性能优化,保留用于极少数情况下的合理性(第 67 项)。通常,复制功能最好由构造函数或工厂提供。 此规则的一个值得注意的例外是数组,最好使用 clone 方法进行复制。 -> - [第 12 项:始终重写 toString 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) -> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) +> - [第 12 项:始终重写 toString 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第12项:始终重写toString方法.md) +> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" index c58e3f7..72b1031 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" @@ -137,5 +137,5 @@ static Comparator hashCodeOrder = Comparator.comparingInt(o -> o.hashCod   总之,无论何时实现具有合理排序的值类,都应该让类实现 Comparable 接口,以便可以在基于比较的集合中轻松地对其实例进行排序,搜索和使用。compareTo 方法的实现中在比较字段的值的时侯,请避免使用 < 和 > 运算符。 而是使用基本类型的包装类中的静态比较方法或比较器接口中的比较器构造方法。 -> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) -> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) \ No newline at end of file +> - [第 13 项:谨慎地重写 clone 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第13项:谨慎地重写clone方法.md) +> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) \ No newline at end of file diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" index a961c22..a451668 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" @@ -63,5 +63,5 @@ public static final Thing[] values() {   总而言之,您应该尽可能地减少程序元素的可访问性(在合理范围内)。在仔细设计了最小的公共 API 之后,您应该防止任何杂散(stray)类、接口或成员成为 API 的一部分。除了作为常量的公共静态 final 字段之外,公共类应该没有公共字段。确保公共的静态 final 字段引用的对象是不可变的。 -> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) -> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) +> - [第 14 项:考虑实现 Comparable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第14项:考虑实现Comparable接口.md) +> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" index df6e2e1..717cd38 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" @@ -57,5 +57,5 @@ public final class Time {   总之,公有类永远都不应该暴露可变字段,但是让公有类暴露不可变的字段其危害比较小。但是,有时候会需要用包级私有的或者私有的嵌套类来暴露字段,无论这个类是可变的还是不可变的。 -> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) -> - [第 17 项:使可变性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) +> - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) +> - [第 17 项:使可变性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" index cffc6d3..e66771c 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" @@ -142,5 +142,5 @@ public static BigInteger safeInstance(BigInteger val) {   最后值得注意的一点与本项中的 Complex 类有关。这个例子只是被用来演示不可变性的,它不是一个工业强度(即产品级)的复数实现。它对复数乘法和除法使用标准的计算公式,会进行不正确的舍入,并对复数 NaN 和无穷大没有提供很好的语义[Kahan91, Smith62, Thomas94]。 -> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) -> - [第 18 项:复合优先于继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) +> - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) +> - [第 18 项:复合优先于继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" index 8f04f3f..6edb5ad 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" @@ -126,5 +126,5 @@ static void walk(Set dogs) {   简而言之,继承的功能非常强大,但是也存在诸多问题,因为它违背了封装原则。只有当子类和超类之间确实存在子类型关系时,使用继承才是恰当的。即便如此,如果子类和超类位于不用的包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性(fragility)。为了避免这种脆弱性,可以使用组合和重定向机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。包装类不仅比子类更加健壮,而且功能也更加强大。 -> - [第 17 项:使可变性最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) -> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) +> - [第 17 项:使可变性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第17项:使可变性最小化.md) +> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" index 4a03c7d..c113f7b 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" @@ -118,5 +118,5 @@ public final class Sub extends Super {   总之,设计一个为了继承的类是一项艰苦的工作。对于它的所有自用模式,你必须提供文档,并且你一旦为它们提供了文档,您必须在类的生命周期中遵守它们。如果你不这样做,子类可能会依赖于超类的实现细节,并且如果超类的实现发生更改,则可能会打破这种依赖。要允许其他人编写有效的子类,您可能还必须导出一个或多个收保护的方法。除非你知道确实需要子类,否则最好通过将类声明为 final 或者确保没有可访问的构造函数来禁止继承。 -> - [第 18 项:复合优先于继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) -> - [第 20 项:接口优于抽象类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) +> - [第 18 项:复合优先于继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第18项:复合优先于继承.md) +> - [第 20 项:接口优于抽象类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" index 6334dbc..3ce6b4f 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" @@ -108,5 +108,5 @@ public abstract class AbstractMapEntry implements Map.Entry {   总而言之,接口通常是定义允许多个实现的类型的最佳方式。如果你要暴露一个重要的接口,你应该强烈考虑提供一个骨架实现来配合它。在可能的范围内,你应该通过接口上的默认方法提供骨架实现,以便接口的所有实现者都可以使用它。也就是说,对接口的限制通常要求骨架实现采用抽象类的形式。 -> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) -> - [第 21 项:为后代设计接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) \ No newline at end of file +> - [第 19 项:要么设计继承并提供文档说明,要么禁止继承](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第19项:要么为继承而设计,并提供文档,要么就禁止继承.md) +> - [第 21 项:为后代设计接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) \ No newline at end of file diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25421\351\241\271\357\274\232\344\270\272\342\200\234\345\220\216\344\273\243\342\200\235\350\256\276\350\256\241\346\216\245\345\217\243.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25421\351\241\271\357\274\232\344\270\272\342\200\234\345\220\216\344\273\243\342\200\235\350\256\276\350\256\241\346\216\245\345\217\243.md" index 237060d..8a73aba 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25421\351\241\271\357\274\232\344\270\272\342\200\234\345\220\216\344\273\243\342\200\235\350\256\276\350\256\241\346\216\245\345\217\243.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25421\351\241\271\357\274\232\344\270\272\342\200\234\345\220\216\344\273\243\342\200\235\350\256\276\350\256\241\346\216\245\345\217\243.md" @@ -39,5 +39,5 @@ default boolean removeIf(Predicate filter) {   因此,在发布之前测试每个新接口至关重要。多个程序员应该以不同的方式实现每个接口。至少,你应该针对三种不同的实现。同样重要的是编写多个客户端程序,使用每个新接口的实例来执行各种任务。这将大大有助于确保每个接口满足其所有预期用途。这些步骤将允许你在发布之前发现接口中的缺陷,这时你仍然可以轻松地更正它们。**虽然可以在发布接口后纠正一些接口缺陷,但您无法指望它。** -> - [第 20 项:接口优于抽象类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) -> - [第 22 项:接口只用于定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) +> - [第 20 项:接口优于抽象类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第20项:接口优先于抽象类.md) +> - [第 22 项:接口只用于定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25422\351\241\271\357\274\232\346\216\245\345\217\243\345\217\252\347\224\250\344\272\216\345\256\232\344\271\211\347\261\273\345\236\213.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25422\351\241\271\357\274\232\346\216\245\345\217\243\345\217\252\347\224\250\344\272\216\345\256\232\344\271\211\347\261\273\345\236\213.md" index f99ff04..0845e97 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25422\351\241\271\357\274\232\346\216\245\345\217\243\345\217\252\347\224\250\344\272\216\345\256\232\344\271\211\347\261\273\345\236\213.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25422\351\241\271\357\274\232\346\216\245\345\217\243\345\217\252\347\224\250\344\272\216\345\256\232\344\271\211\347\261\273\345\236\213.md" @@ -51,5 +51,5 @@ public class Test {   简而言之,接口应该只被用来定义类型,他们不应该被用来导出常量。 -> - [第 21 项:为后代设计接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) -> - [第 23 项:类层次优于标签类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) +> - [第 21 项:为后代设计接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第21项:为“后代”设计接口.md) +> - [第 23 项:类层次优于标签类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" index fb567ec..b82e98f 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" @@ -88,5 +88,5 @@ class Square extends Rectangle {   简而言之,标签类很少有适用的时候。当你想要编写一个包含显示标签字段的类时,应该考虑一下,这个标签是否可以被取消,这个类是否可以用类层次来代替。当你遇到一个包含标签字段的现有类时,就要考虑将它重构到一个层次结构中去。 -> - [第 22 项:接口只用于定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) -> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) +> - [第 22 项:接口只用于定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第22项:接口只用于定义类型.md) +> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25424\351\241\271\357\274\232\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273\344\274\230\344\272\216\351\235\236\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25424\351\241\271\357\274\232\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273\344\274\230\344\272\216\351\235\236\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273.md" index 235b60e..e3cf179 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25424\351\241\271\357\274\232\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273\344\274\230\344\272\216\351\235\236\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25424\351\241\271\357\274\232\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273\344\274\230\344\272\216\351\235\236\351\235\231\346\200\201\346\210\220\345\221\230\347\261\273.md" @@ -41,5 +41,5 @@ public class MySet extends AbstractSet {   总结一下,有四种不同的嵌套类,每种都有它的用途。如果嵌套类需要在单个方法之外可见,或者太长而不适合在方法中使用,请使用成员类。如果成员类的每个实例都需要一个指向外围类实例的引用,请将其设置为非静态;否则,就将它设置为静态。假设这个类属于一个方法的内部,如果你只需要从一个地方创建实例,并且有一个预先存在的类型来表示这个类,则将其设为匿名类; 否则,让它成为局部类。 -> - [第 23 项:类层次优于标签类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) -> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) +> - [第 23 项:类层次优于标签类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第23项:类层次优于标签类.md) +> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25425\351\241\271\357\274\232\351\231\220\345\210\266\346\272\220\346\226\207\344\273\266\345\217\252\346\234\211\344\270\200\344\270\252\351\241\266\347\272\247\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25425\351\241\271\357\274\232\351\231\220\345\210\266\346\272\220\346\226\207\344\273\266\345\217\252\346\234\211\344\270\200\344\270\252\351\241\266\347\272\247\347\261\273.md" index 831a8be..4529122 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25425\351\241\271\357\274\232\351\231\220\345\210\266\346\272\220\346\226\207\344\273\266\345\217\252\346\234\211\344\270\200\344\270\252\351\241\266\347\272\247\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25425\351\241\271\357\274\232\351\231\220\345\210\266\346\272\220\346\226\207\344\273\266\345\217\252\346\234\211\344\270\200\344\270\252\351\241\266\347\272\247\347\261\273.md" @@ -61,5 +61,5 @@ public class Test {   教训很明确:永远不要将多个顶级类或接口放在单个源文件中。遵循这个规则就能够确保在编译的时候不会出现一个类有多个定义。这反过来保证了编译生成的类文件以及生成程序的行为与源文件传递给编译器的顺序无关。 -> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) -> - [第 26 项:请不要使用原生态类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) +> - [第 24 项:静态成员类优于非静态成员类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第24项:静态成员类优于非静态成员类.md) +> - [第 26 项:请不要使用原生态类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25426\351\241\271\357\274\232\344\270\215\350\246\201\344\275\277\347\224\250\345\216\237\347\224\237\346\200\201\347\261\273\345\236\213.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25426\351\241\271\357\274\232\344\270\215\350\246\201\344\275\277\347\224\250\345\216\237\347\224\237\346\200\201\347\261\273\345\236\213.md" index 3be7b68..f5c60f3 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25426\351\241\271\357\274\232\344\270\215\350\246\201\344\275\277\347\224\250\345\216\237\347\224\237\346\200\201\347\261\273\345\236\213.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25426\351\241\271\357\274\232\344\270\215\350\246\201\344\275\277\347\224\250\345\216\237\347\224\237\346\200\201\347\261\273\345\236\213.md" @@ -148,5 +148,5 @@ if (o instanceof Set) { // Raw type | 泛型方法 | static List asList(E[] a) | 第 30 项 | | 类型令牌 | String.class | 第 33 项 | -> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) -> - [第 27 项:消除非受检的警告](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) +> - [第 25 项:限制源文件为单个顶级类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第25项:限制源文件只有一个顶级类.md) +> - [第 27 项:消除非受检的警告](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25427\351\241\271\357\274\232\346\266\210\351\231\244\351\235\236\345\217\227\346\243\200\350\255\246\345\221\212.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25427\351\241\271\357\274\232\346\266\210\351\231\244\351\235\236\345\217\227\346\243\200\350\255\246\345\221\212.md" index 31022ad..e2f1f31 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25427\351\241\271\357\274\232\346\266\210\351\231\244\351\235\236\345\217\227\346\243\200\350\255\246\345\221\212.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25427\351\241\271\357\274\232\346\266\210\351\231\244\351\235\236\345\217\227\346\243\200\350\255\246\345\221\212.md" @@ -77,5 +77,5 @@ public T[] toArray(T[] a) {   总而言之,非受检警告很重要,不要忽略它们。每一条警告都表示可能在运行时抛出`ClassCastException`异常。要尽最大的努力消除这些警告。如果无法消除非受检警告,同时可以证明引起警告的代码是类型安全的,就可以在尽可能小的范围中,用`@SuppressWarnings("unchecked")`注解压制该警告。要用注释把压制该警告的原因记录下来。 -> - [第 26 项:请不要使用原生态类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) -> - [第 28 项:列表优于数组](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) +> - [第 26 项:请不要使用原生态类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第26项:不要使用原生态类型.md) +> - [第 28 项:列表优于数组](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25428\351\241\271\357\274\232\345\210\227\350\241\250\344\274\230\345\205\210\344\272\216\346\225\260\347\273\204.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25428\351\241\271\357\274\232\345\210\227\350\241\250\344\274\230\345\205\210\344\272\216\346\225\260\347\273\204.md" index 673dd3c..683ac17 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25428\351\241\271\357\274\232\345\210\227\350\241\250\344\274\230\345\205\210\344\272\216\346\225\260\347\273\204.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25428\351\241\271\357\274\232\345\210\227\350\241\250\344\274\230\345\205\210\344\272\216\346\225\260\347\273\204.md" @@ -122,5 +122,5 @@ public class Chooser {   总之,数组和泛型具有非常不同的类型规则。数组是协变的和可具体化的; 泛型是不变的且可以被擦除。因此,数组提供运行时的类型安全,但不提供编译时的类型安全,反之,对于泛型也一样。通常,数组和泛型不能很好地混合使用。如果你发现自己将它们混合起来使用,并且得到了编译时错误或警告,你的第一个反应就应该是用列表替换数组。 -> - [第 27 项:消除非受检的警告](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) -> - [第 29 项:优先考虑泛型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) +> - [第 27 项:消除非受检的警告](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第27项:消除非受检警告.md) +> - [第 29 项:优先考虑泛型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" index 8986369..5117753 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" @@ -164,5 +164,5 @@ class DelayQueue implements BlockingQueue   总而言之,使用泛型比使用需要在客户端代码中进行转换的类型来得更加安全,也更加容易。在设计新类型的时候,要确保它们不需要这种转换就可以使用。这通常意味着要把类做成泛型。如果你现在有任何类型应该是通用的但却不是通用的,就把现有的类型都泛型化。这对于这些类型的新用户来说会变得更加轻松,又不会破坏现有的客户端(第 26 项)。 -> - [第 28 项:列表优于数组](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) -> - [第 30 项:优先考虑泛型方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) +> - [第 28 项:列表优于数组](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第28项:列表优先于数组.md) +> - [第 30 项:优先考虑泛型方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25430\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213\346\226\271\346\263\225.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25430\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213\346\226\271\346\263\225.md" index e9be277..bbfa090 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25430\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213\346\226\271\346\263\225.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25430\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213\346\226\271\346\263\225.md" @@ -124,5 +124,5 @@ public static > E max(Collection c) {   总而言之,泛型方法就像泛型一样,使用起来比要求客户端转换输入参数并返回值的方法来得更加安全,也更加容易。就像类型一样,你应该确保你的方法可以不用转换就能使用,这通常意味着要将它们泛型化。并且就像类型一样,还应该将现有的方法泛型化,使新用户使用起来更加轻松,且不会破坏现有的客户端(第 26 项)。 -> - [第 29 项:优先考虑泛型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) -> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) +> - [第 29 项:优先考虑泛型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第29项:优先考虑泛型.md) +> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25431\351\241\271\357\274\232\345\210\251\347\224\250\346\234\211\351\231\220\345\210\266\351\200\232\351\205\215\347\254\246\346\235\245\346\217\220\345\215\207API\347\232\204\347\201\265\346\264\273\346\200\247.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25431\351\241\271\357\274\232\345\210\251\347\224\250\346\234\211\351\231\220\345\210\266\351\200\232\351\205\215\347\254\246\346\235\245\346\217\220\345\215\207API\347\232\204\347\201\265\346\264\273\346\200\247.md" index d96d7f9..9ed39a1 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25431\351\241\271\357\274\232\345\210\251\347\224\250\346\234\211\351\231\220\345\210\266\351\200\232\351\205\215\347\254\246\346\235\245\346\217\220\345\215\207API\347\232\204\347\201\265\346\264\273\346\200\247.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25431\351\241\271\357\274\232\345\210\251\347\224\250\346\234\211\351\231\220\345\210\266\351\200\232\351\205\215\347\254\246\346\235\245\346\217\220\345\215\207API\347\232\204\347\201\265\346\264\273\346\200\247.md" @@ -215,5 +215,5 @@ private static void swapHelper(List list, int i, int j) {   总而言之,在 API 中使用通配符类型虽然比较需要技巧,但是使 API 变得灵活得多。如果编写的是将被广泛使用的类库,则一定要适当地利用通配符类型。记住基本的原则:producer-extends, consumer-super (PECS)。还要记住所有的 comparable 和 comparator 都是消费者。 -> - [第 30 项:优先考虑泛型方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) -> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) +> - [第 30 项:优先考虑泛型方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第30项:优先考虑泛型方法.md) +> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25432\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\347\273\223\345\220\210\346\263\233\345\236\213\345\222\214\345\217\257\345\217\230\345\217\202\346\225\260.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25432\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\347\273\223\345\220\210\346\263\233\345\236\213\345\222\214\345\217\257\345\217\230\345\217\202\346\225\260.md" index c1b9527..ca9870c 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25432\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\347\273\223\345\220\210\346\263\233\345\236\213\345\222\214\345\217\257\345\217\230\345\217\202\346\225\260.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25432\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\347\273\223\345\220\210\346\263\233\345\236\213\345\222\214\345\217\257\345\217\230\345\217\202\346\225\260.md" @@ -136,5 +136,5 @@ public static void main(String[] args) {   总之,可变参数和泛型不能很好地交互,因为可变参数的灵活性是在数组上构建的有漏洞的抽象,并且数组具有与泛型不同的类型规则。虽然泛型可变参数不是类型安全的,但它们是合法的。如果你选择使用泛型(或参数化)可变参数编写方法,请首先确保该方法是类型安全的,然后使用`@SafeVarargs`对其进行注释,以免使用起来不开心。 -> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) -> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) +> - [第 31 项:利用有限制通配符来提升 API 的灵活性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第31项:利用有限制通配符来提升API的灵活性.md) +> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25433\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\347\261\273\345\236\213\345\256\211\345\205\250\347\232\204\345\274\202\346\236\204\345\256\271\345\231\250.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25433\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\347\261\273\345\236\213\345\256\211\345\205\250\347\232\204\345\274\202\346\236\204\345\256\271\345\231\250.md" index a7ea487..c70a578 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25433\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\347\261\273\345\236\213\345\256\211\345\205\250\347\232\204\345\274\202\346\236\204\345\256\271\345\231\250.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25433\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\347\261\273\345\236\213\345\256\211\345\205\250\347\232\204\345\274\202\346\236\204\345\256\271\345\231\250.md" @@ -117,5 +117,5 @@ static Annotation getAnnotation(AnnotatedElement element, String annotationTypeN   总而言之,集合 API 说明了泛型的一般用法,限制你每个容器只能有固定数目的类型参数。你可以通过将类型参数放在键上面而不是容器上来避开这一限制。对于这种类型安全的异构容器,可以使用 Class 对象作为键。以这种方式使用的 Class 对象称作类型令牌。你也可以使用定制的键类型。例如,用一个 DatabaseRow 类型表示一个数据库行(容器),用泛型 Column\作为它的键。 -> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) -> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) +> - [第 32 项:谨慎并用泛型和可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第32项:明智地结合泛型和可变参数.md) +> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" index ba43035..8cc4119 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" @@ -295,5 +295,5 @@ public static Operation inverse(Operation op) {   总之,枚举类型跟 int 常量相比,优点是显而易见的。枚举更具有可读性,更安全,更强大。许多枚举不需要显示构造函数或成员,但许多枚举则受益于将每个常量与数据【枚举的成员】相关联并提供这个数据影响行为的方法。在这种相对少见的情况下,特定于常量的方法要优先于启用自有值的枚举。如果多个枚举常量同时共享相同的行为,则考虑策略枚举。 -> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) -> - [第 35 项:用实例域代替序数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) +> - [第 33 项:优先考虑类型安全的异构容器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第05章:泛型/第33项:优先考虑类型安全的异构容器.md) +> - [第 35 项:用实例域代替序数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" index 55ee73e..59ad1ed 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" @@ -30,5 +30,5 @@ public enum Ensemble {   Enum 规范中谈到 ordinal 时是这么写的:“大多数程序猿都不需要这个方法。它这么设计的目的是用于像 EnumSet 和 EnumMap 这种基于枚举的通用数据结构的。”除非你在编写的是这种数据结构,否则最好避免使用 ordinal 方法。 -> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) -> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) +> - [第 34 项:用 enum 代替 int 常量](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) +> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" index 6c2c3cf..2146dbe 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" @@ -45,5 +45,5 @@ text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));   总而言之,**正是因为枚举类型要用在几个(Set)中,所以没有理由用位域来表示它**。EnumSet 类集位域的简洁和性能优势以及第 34 项中所述的枚举类型的所有优点于一身。EnumSet 的一个真正的缺点是,从 Java 9 开始,它不可能创建一个不可变的 EnumSet,但这可能会在即将发布的版本中得到补救。在此期间,您可以使用 Collections.unmodifiableSet 包装 EnumSet,但简洁性和性能将受到影响。 -> - [第 35 项:用实例域代替序数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) -> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) +> - [第 35 项:用实例域代替序数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第35项:用实例域代替序数.md) +> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" index 957dd63..9950bae 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" @@ -170,5 +170,5 @@ public enum Phase {   总而言之,**最好不要用序数来索引数组,而要使用 EnumMap**。如果你所表示的这种关系是多维的,就使用 EnumMap<..., EnumMap<...>>。应用程序的程序猿在一般情况下都不适用 Enum.ordinal,即使要用也很少,因此这是一种特殊情况(第 35 项) -> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) -> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) +> - [第 36 项:用 EnumSet 代替位域](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) +> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25438\351\241\271\357\274\232\347\224\250\346\216\245\345\217\243\346\250\241\346\213\237\345\217\257\346\211\251\345\261\225\347\232\204\346\236\232\344\270\276.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25438\351\241\271\357\274\232\347\224\250\346\216\245\345\217\243\346\250\241\346\213\237\345\217\257\346\211\251\345\261\225\347\232\204\346\236\232\344\270\276.md" index d3fe2f6..ace3982 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25438\351\241\271\357\274\232\347\224\250\346\216\245\345\217\243\346\250\241\346\213\237\345\217\257\346\211\251\345\261\225\347\232\204\346\236\232\344\270\276.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25438\351\241\271\357\274\232\347\224\250\346\216\245\345\217\243\346\250\241\346\213\237\345\217\257\346\211\251\345\261\225\347\232\204\346\236\232\344\270\276.md" @@ -108,5 +108,5 @@ private static void test(Collection opSet, double x, double   总而言之,**虽然无法编写可扩展的枚举类型,却可以通过编写接口以及实现该接口的基础枚举类型,对它进行模拟**。这样允许客户端编写自己的枚举类型来实现接口。如果 API 是根据接口编写的,那么在可以使用基础枚举类型的任何地方,也都可以使用这些枚举【自己编写的枚举】。 -> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) -> - [第 39 项:注解优先于命名模式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) +> - [第 37 项:用 EnumMap 代替序数索引](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第37项:用EnumMap代替序数索引.md) +> - [第 39 项:注解优先于命名模式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" index 2d0b167..f81c5e3 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" @@ -257,5 +257,5 @@ if (m.isAnnotationPresent(ExceptionTest.class) || m.isAnnotationPresent(Exceptio   也就是说,除了“工具铁匠(toolsmiths————特定的程序猿)”之外,大多数程序猿都不必定义注解类型。**但是所有的程序猿都应该使用 Java 平台所提供的预定义的注解类型(第 40、27 项)**。还要考虑使用 IDE 或者静态分析工具所提供的任何注解。这种注解可以提升由这些工具所提供的诊断信息的质量。但是要注意这些注解还没有标准化,因此如果变换工具或者形成标准,就有很多工作要做了。 -> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) -> - [第 40 项:坚持使用 Override 注解](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) +> - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) +> - [第 40 项:坚持使用 Override 注解](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" index 411e4e8..c7a7da9 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" @@ -70,5 +70,5 @@ from a supertype   总而言之,如果在你想要的每个方法声明中使用 Override 注解来覆盖超类声明,编译器就可以替你防止出现大量的错误,但有一个例外。在具体的类中,不必标注你确信覆盖了抽象方法声明的方法(虽然这么做也没什么坏处)。 -> - [第 39 项:注解优先于命名模式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) -> - [第 41 项:用标记接口定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) +> - [第 39 项:注解优先于命名模式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第39项:注解优先于命名模式.md) +> - [第 41 项:用标记接口定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25441\351\241\271\357\274\232\347\224\250\346\240\207\350\256\260\346\216\245\345\217\243\345\256\232\344\271\211\347\261\273\345\236\213.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25441\351\241\271\357\274\232\347\224\250\346\240\207\350\256\260\346\216\245\345\217\243\345\256\232\344\271\211\347\261\273\345\236\213.md" index a88f1f4..63897a3 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25441\351\241\271\357\274\232\347\224\250\346\240\207\350\256\260\346\216\245\345\217\243\345\256\232\344\271\211\347\261\273\345\236\213.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25441\351\241\271\357\274\232\347\224\250\346\240\207\350\256\260\346\216\245\345\217\243\345\256\232\344\271\211\347\261\273\345\236\213.md" @@ -18,5 +18,5 @@   从某种意义上说,本项与 22 项中“如果不想定义类型就不要使用接口”的说法相反。本项最接近的意思是说:如果想要定义类型,一定要使用接口。 -> - [第 40 项:坚持使用 Override 注解](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) -> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) +> - [第 40 项:坚持使用 Override 注解](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) +> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25442\351\241\271\357\274\232Lambda\344\274\230\345\205\210\344\272\216\345\214\277\345\220\215\347\261\273.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25442\351\241\271\357\274\232Lambda\344\274\230\345\205\210\344\272\216\345\214\277\345\220\215\347\261\273.md" index 39db189..57bddfa 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25442\351\241\271\357\274\232Lambda\344\274\230\345\205\210\344\272\216\345\214\277\345\220\215\347\261\273.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25442\351\241\271\357\274\232Lambda\344\274\230\345\205\210\344\272\216\345\214\277\345\220\215\347\261\273.md" @@ -97,5 +97,5 @@ public enum Operation {   总之,从 Java 8 开始,lambda 是迄今为止表示小函数对象的最佳方式。**除非必须创建非功能接口类型的实例,否则不要对函数对象使用匿名类**。另外,请记住,lambda 使得通过使用对象来代表小函数变得如此容易,以至于它打开了以前在 Java 中不实用的函数式编程技术的大门。 -> - [第 41 项:用标记接口定义类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) -> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) +> - [第 41 项:用标记接口定义类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第41项:用标记接口定义类型.md) +> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25443\351\241\271\357\274\232\346\226\271\346\263\225\345\274\225\347\224\250\344\274\230\345\205\210\344\272\216Lambda.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25443\351\241\271\357\274\232\346\226\271\346\263\225\345\274\225\347\224\250\344\274\230\345\205\210\344\272\216Lambda.md" index 5dc41ea..147584c 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25443\351\241\271\357\274\232\346\226\271\346\263\225\345\274\225\347\224\250\344\274\230\345\205\210\344\272\216Lambda.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25443\351\241\271\357\274\232\346\226\271\346\263\225\345\274\225\347\224\250\344\274\230\345\205\210\344\272\216Lambda.md" @@ -44,5 +44,5 @@ service.execute(() -> action());   总之,方法引用通常提供一种更简洁的 lambda 替代方案。**在使用方法引用可以更简短更清晰的地方,就使用方法引用,如果无法使代码更简短更清晰的地方就坚持使用 lambda。(Where method references are shorter and clearer, use them; where they aren’t, stick with lambdas.)** -> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) -> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) +> - [第 42 项:Lambda 优先于匿名类](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第42项:Lambda优先于匿名类.md) +> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25444\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\207\275\346\225\260\346\216\245\345\217\243.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25444\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\207\275\346\225\260\346\216\245\345\217\243.md" index b4231bf..6950a4f 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25444\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\207\275\346\225\260\346\216\245\345\217\243.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25444\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\207\275\346\225\260\346\216\245\345\217\243.md" @@ -57,5 +57,5 @@ interface EldestEntryRemovalFunction{   总而言之,既然 Java 已经有了 lambda,那么在设计 API 时必须考虑到 lambda。接受输入上的功能接口类型并在输出上返回它们。通常最好使用 java.util.function.Function 中提供的标准接口,但请注意那些相对少见的情况,那就最好编写自己的功能接口。 -> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) -> - [第 45 项:谨慎使用 Stream](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) +> - [第 43 项:方法引用优先于 Lambda](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第43项:方法引用优先于Lambda.md) +> - [第 45 项:谨慎使用 Stream](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" index bb7e99f..6f440ea 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" @@ -183,5 +183,5 @@ private static List newDeck() {   总之,一些任务最好用流完成,其他任务最好用遍历完成。通过组合这两种方法可以最好地完成许多任务。选择哪种方法用于任务没有硬性规定,但有一些有用的启发式方法。在许多情况下,将清楚使用哪种方法; 在某些情况下,它不会。**如果你不确定某个任务是否更适合流或遍历,那么就两个都尝试一下,并看一下哪个更好**。 -> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) -> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) +> - [第 44 项:坚持使用标准的函数接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第44项:坚持使用标准的函数接口.md) +> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" index acd0541..d175a8c 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" @@ -102,5 +102,5 @@ Map freq = words.collect(groupingBy(String::toLowerCase, counting(   总之,流管道编程的本质是无副作用的功能对象。这适用于传递给流和相关对象的几乎所有的函数对象(This applies to all of the many function objects passed to streams and related objects)。终端操作 forEach 仅应用于报告流执行的计算结果,而不是用于执行计算。为了正确使用流,你必须了解收集器。最重要的收集器工厂是 toList,toSet,toMap,groupingBy 和 join。 -> - [第 45 项:谨慎使用 Stream](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) -> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) +> - [第 45 项:谨慎使用 Stream](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第45项:谨慎使用Stream.md) +> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" index d0395a9..e50346d 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" @@ -139,5 +139,5 @@ public static Stream> of(List list) {   总之,在编写返回元素序列的方法时,请记住,你的某些用户可能希望将它们作为流进行处理,而其他用户可能希望使用它们进行遍历。尽量适应这两个群体。如果返回集合是可行的,那么就返回集合。如果你已经拥有集合中的元素,或者序列中的元素数量很小足以证明创建新元素是正确的,那么就返回标准集合,例如 ArrayList。否则,请考虑实现自定义的集合,就像我们为幂集所做的那样。如果返回集合是不可行的,则返回一个流或可迭代的【类型】,无论哪个看起来更自然。如果在将来的 Java 版本中,Stream 接口声明被修改为扩展(extend)Iterable,那么你应该随意返回流,因为它们将允许进行流处理和遍历。 -> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) -> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) +> - [第 46 项:优先选择 Stream 中无副作用的函数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第46项:优先选择Stream中无副作用的函数.md) +> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25448\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream\345\271\266\350\241\214.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25448\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream\345\271\266\350\241\214.md" index 556a424..9562683 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25448\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream\345\271\266\350\241\214.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25448\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream\345\271\266\350\241\214.md" @@ -70,5 +70,5 @@ static long pi(long n) {   总之,除非你有充分的理由相信它将保持计算的正确性并提高其速度,否则就不应该尝试并行化流管道。不恰当地并行化流的成本可能是程序失败或性能灾难。如果你认为并行性可能是合理的,请确保在并行运行时代码保持【运行结果的】正确,并在实际条件下进行详细的性能测试。如果你的代码仍然正确并且这些实验证明你对性能提升的猜疑,那么才能在生产环境的代码中使用并行化流(If your code remains correct and these experiments bear out your suspicion of increased performance, then and only then parallelize the stream in production code.)。 -> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) -> - [第 49 项:检查参数的有效性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) +> - [第 47 项:Stream 要优先用 Collection 作为返回类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第47项:Stream要优先用Collection作为返回类型.md) +> - [第 49 项:检查参数的有效性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25449\351\241\271\357\274\232\346\243\200\346\237\245\345\217\202\346\225\260\347\232\204\346\234\211\346\225\210\346\200\247.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25449\351\241\271\357\274\232\346\243\200\346\237\245\345\217\202\346\225\260\347\232\204\346\234\211\346\225\210\346\200\247.md" index bffb165..3160b97 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25449\351\241\271\357\274\232\346\243\200\346\237\245\345\217\202\346\225\260\347\232\204\346\234\211\346\225\210\346\200\247.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25449\351\241\271\357\274\232\346\243\200\346\237\245\345\217\202\346\225\260\347\232\204\346\234\211\346\225\210\346\200\247.md" @@ -62,5 +62,5 @@ private static void sort(long a[], int offset, int length) {   简而言之,每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制。应该把这些限制写到文档中,并且在这个方法体的开头处,通过显式的检查来校验这些限制。养成这样的习惯是非常重要的。只要有效性检查有一次失败,你为必要的有效性检查所付出的努力便都可以连本带利地得到偿还了。 -> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) -> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) +> - [第 48 项:谨慎使用 Stream 并行](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第07章:Lambda和Stream/第48项:谨慎使用Stream并行.md) +> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" index 6444a1f..9c5d48d 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" @@ -101,5 +101,5 @@ public Date end() {   简而言之,如果类具有从客户端得到或者返回给客户端的可变组件,类就必须保护性地拷贝这些组件。如果拷贝的成本受到限制,并且类信任它的客户端不会不恰当地修改组件,就可以在文档中指明客户端的职责是不得修改受到影响的组件,以此来代替保护性拷贝。 -> - [第 49 项:检查参数的有效性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) -> - [第 51 项:谨慎设计方法签名](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) +> - [第 49 项:检查参数的有效性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第49项:检查参数的有效性.md) +> - [第 51 项:谨慎设计方法签名](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" index 1f0c78f..1a3f631 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" @@ -24,5 +24,5 @@ public enum TemperatureScale { FAHRENHEIT, CELSIUS }   Thermometer.newInstance(TemperatureScale.CELSIUS)不仅比 Thermometer.newInstance(true)更有用,而且你还可以在未来的发行版本中将 KELVIN 添加到 TemperatureScale 中,无需非得给 Thermometer 添加新的静态工厂。你还可以将依赖于温度刻度单位的代码重构到枚举常量的方法中(第 34 项)。例如,每个刻度单位都可以有一个方法,它带有一个 double 值,并将它规格化为摄氏度。 -> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) -> - [第 52 项:慎用重载](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) +> - [第 50 项:必要时进行保护性拷贝](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第50项:必要时进行保护性拷贝.md) +> - [第 52 项:慎用重载](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" index 415ceb3..88d6851 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" @@ -139,5 +139,5 @@ public boolean contentEquals(StringBuffer sb) {   简而言之,能够重载方法并不意味着就应该重载方法。一般情况下,对于多个具有相同参数数目的方法来说,应该尽量避免重载方法。在某些情况下,特别是涉及构造函数的时候,要遵循这条建议也许是不可能的。在这种情况下,至少应该避免这样的情形:同一组参数只需要经过类型转换就可以被传递给不用的重载方法。如果不能避免这种情形,例如,因为正在改造一个现有的类来实现新的接口,就应该保证:当传递同样的参数时,所有重载方法的行为必须一致。如果不能做到这一点,程序猿就很难有效地使用被重载的方法或者构造器,它们就不能理解它为什么不能正常地工作。 -> - [第 51 项:谨慎设计方法签名](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) -> - [第 53 项:慎用可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) +> - [第 51 项:谨慎设计方法签名](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) +> - [第 53 项:慎用可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25453\351\241\271\357\274\232\346\205\216\347\224\250\345\217\257\345\217\230\345\217\202\346\225\260.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25453\351\241\271\357\274\232\346\205\216\347\224\250\345\217\257\345\217\230\345\217\202\346\225\260.md" index 23c850b..6f0b352 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25453\351\241\271\357\274\232\346\205\216\347\224\250\345\217\257\345\217\230\345\217\202\346\225\260.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25453\351\241\271\357\274\232\346\205\216\347\224\250\345\217\257\345\217\230\345\217\202\346\225\260.md" @@ -62,5 +62,5 @@ public void foo(int a1, int a2, int a3, int... rest) { }   总之,当您需要定义参数数量不确定的方法时,可变参数非常有用。在可变参数前加上任何必需的参数,并注意使用可变参数【可能】造成的性能后果。 -> - [第 52 项:慎用重载](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) -> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) \ No newline at end of file +> - [第 52 项:慎用重载](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第52项:慎用重载.md) +> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) \ No newline at end of file diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" index 51c34ac..2b28105 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" @@ -70,6 +70,6 @@ return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);   总之,**永远不要返回 null 来代替【返回】空数组或集合**。它会让你的 API 更难以使用并且更容易出错,并且它没有性能优势。 -> - [第 53 项:慎用可变参数](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) -> - [第 55 项:谨慎返回 optinal](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) +> - [第 53 项:慎用可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) +> - [第 55 项:谨慎返回 optinal](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" index 82ddb2f..f18774c 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" @@ -112,5 +112,5 @@ streamOfOptionals.flatMap(Optional::stream)   总之,如果你发现自己编写的方法无法始终返回值,并且你认为【使用该】方法的用户每次调用它时都考虑这种可能性,那么你应该返回一个 optional。但是,你应该意识到返回 optional 会真正产生性能影响;对于对性能有要求的方法(for performance-critical methods),最好返回 null 或抛出异常。最后,除了作为返回值,你应该最大限度的不在其他地方使用 optional(you should rarely use an optional in any other capacity than as a return value.)。 -> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) -> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) +> - [第 54 项:返回零长度的数组或者集合,而不是 null](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第54项:返回零长度的数组或者集合,而不是null.md) +> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" index 7407339..b7faa0e 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" @@ -156,5 +156,5 @@ public @interface ExceptionTest {   总而言之,要为 API 编写文档,文档注释是最好、最有效的途径。对于所有可导出的 API 元素来说,使用文档注释应该被看作是强制性的。要采用一致的风格来遵循标准的约定。记住,在文档注释内部出现任何 HTML 标签都是允许的,但是 HTML 元字符必须要经过转义。 -> - [第 55 项:谨慎返回 optinal](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) -> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) +> - [第 55 项:谨慎返回 optinal](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第55项:谨慎返回optional.md) +> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md" index 4825bfb..6196844 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md" @@ -78,5 +78,5 @@ for (int i = 0, n = expensiveComputation(); i < n; i++) {   最后一种将局部变量的作用域最小化的方法时**使方法【体尽可能】小而集中** ,如果把两个操作(activity)合并到同一个方法中,与其中一个操作相关的局部变量就有可能会出现在执行另一个操作的代码范围之内。为了防止这种情况发生,只要把这个方法分成两个,每个方法各执行一个操作。 -> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) -> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) +> - [第 56 项:为所有导出的 API 元素编写文档注释](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第56项:为所有导出的API元素编写文档注释.md) +> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md" index 6b3e594..c4600ab 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md" @@ -106,5 +106,5 @@ public interface Iterable {   总之,for-each 循环在清晰度,灵活性和预防出错方面提供了超越传统 for 循环的优势,而且不会有性能损失。在使用中尽可能让 for-each 循环优先于 for 循环。 -> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) -> - [第 59 项:了解和使用类库](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) +> - [第 57 项:将局部变量的作用域最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第57项:将局部变量的作用域最小化.md) +> - [第 59 项:了解和使用类库](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md" index 82815e9..f7383c5 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md" @@ -58,5 +58,5 @@ public static void main(String[] args) throws IOException {   总而言之,不要重新发明轮子。如果你需要做的事情看起来是十分常见的,有可能类库中已经有某个类完成了这样的工作。如果确实是这样,就使用它;如果你不知道是否存在这样的类,就去查一查。一般而言,类库的代码可能比你自己编写的代码更好一些,并且会随着时间的推移不断改进。这并不是在影射你作为一只程序猿的能力。从经济角度的分析表明:类库代码受到的关注远远超过大多数普通程序猿在同样的功能上所能给予的投入。 -> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) -> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) +> - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md) +> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25460\351\241\271\357\274\232\345\246\202\346\236\234\351\234\200\350\246\201\347\262\276\347\241\256\347\232\204\347\255\224\346\241\210\357\274\214\350\257\267\351\201\277\345\205\215\344\275\277\347\224\250float\345\222\214double.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25460\351\241\271\357\274\232\345\246\202\346\236\234\351\234\200\350\246\201\347\262\276\347\241\256\347\232\204\347\255\224\346\241\210\357\274\214\350\257\267\351\201\277\345\205\215\344\275\277\347\224\250float\345\222\214double.md" index 027a1de..5b20a84 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25460\351\241\271\357\274\232\345\246\202\346\236\234\351\234\200\350\246\201\347\262\276\347\241\256\347\232\204\347\255\224\346\241\210\357\274\214\350\257\267\351\201\277\345\205\215\344\275\277\347\224\250float\345\222\214double.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25460\351\241\271\357\274\232\345\246\202\346\236\234\351\234\200\350\246\201\347\262\276\347\241\256\347\232\204\347\255\224\346\241\210\357\274\214\350\257\267\351\201\277\345\205\215\344\275\277\347\224\250float\345\222\214double.md" @@ -73,5 +73,5 @@ public static void main(String[] args) {   总而言之,对于任何需要精确答案的计算任务,请不要使用 float 或者 double。如果你想让系统来记录十进制小数点,并且不介意因为不使用基本类型而带来的不便,就请使用 BigDecimal。使用 BigDecimal 还有一些额外的好处,它允许你完全控制舍入,只要执行需要舍入的操作,就可以从八种舍入模式中进行选择。如果你使用合法的舍入行为执行业务计算,这就能派上用场。如果性能非常关键,并且你又不介意自己记录十进制小数点,而且涉及的数值又不会太大,使用 int 或者 long。如果数值范围没有超过 9 为十进制数字,就可以使用 int;如果不超过 18 位数字,就可以使用 long。如果数值可能超过 18 位数字,就必须使用 BigDecimal。 -> - [第 59 项:了解和使用类库](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) -> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) +> - [第 59 项:了解和使用类库](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第59项:了解和使用类库.md) +> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md" index 8dbeceb..3b4084c 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md" @@ -61,5 +61,5 @@ public static void main(String[] args) {   总之,当可以选择的时候,基本类型要优先于装箱基本类型。基本类型更加简单,也更加快速。如果必须使用装箱基本类型,要特别小心!**自动装箱减少了使用装箱基本类型的繁琐性,但是并没有减少它的风险** 。当程序使用==操作符比较两个装箱基本类型时,它做了个同一性比较,这几乎可以肯定不是你想要的。当程序进行涉及装箱和拆箱基本类型的混合类型计算时,它会进行拆箱,而且,**当你的程序做自动拆箱操作的时候,它可能会(can)抛出一个 NullPointerException 异常** 。最后,当程序装箱了基本类型值时,它会导致不必要的高开销。 -> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) -> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) +> - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md) +> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md" index d02b9e0..f41cd55 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md" @@ -71,5 +71,5 @@ public final class ThreadLocal {   总而言之,如果可以使用更加合适的数据类型,或者可以编写更加适当的数据类型,就应该避免使用字符串来表示对象。若使用不当,字符串会比其他的类型更加笨拙、更加不灵活、速度更慢,也更容易出错。经常被错误地用字符串来代替的类型包括基本类型、枚举类型和聚合类型。 -> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) -> - [第 63 项:了解字符串连接的性能](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) +> - [第 61 项:基本类型优先于装箱基本类型](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第61项:基本类型优先于装箱基本类型.md) +> - [第 63 项:了解字符串连接的性能](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25463\351\241\271\357\274\232\346\263\250\346\204\217\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245\347\232\204\346\200\247\350\203\275.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25463\351\241\271\357\274\232\346\263\250\346\204\217\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245\347\232\204\346\200\247\350\203\275.md" index a295bb4..8b2ea6e 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25463\351\241\271\357\274\232\346\263\250\346\204\217\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245\347\232\204\346\200\247\350\203\275.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25463\351\241\271\357\274\232\346\263\250\346\204\217\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245\347\232\204\346\200\247\350\203\275.md" @@ -29,5 +29,5 @@ public String statement() {   原则很简单:**不要使用字符串拼接操作符来合并多个字符串** ,除非性能无关紧要。相反,应该使用 StringBuilder 的 append 方法。另一种方法是,使用一个字符数组,或者每次只处理一个字符串,而不是将它们组合起来。 -> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) -> - [第 64 项:通过接口引用对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) +> - [第 62 项:如果其他类型更适合,则尽量避免使用字符串](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第62项:如果其他类型更适合,则尽量避免使用字符串.md) +> - [第 64 项:通过接口引用对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25464\351\241\271\357\274\232\351\200\232\350\277\207\346\216\245\345\217\243\345\274\225\347\224\250\345\257\271\350\261\241.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25464\351\241\271\357\274\232\351\200\232\350\277\207\346\216\245\345\217\243\345\274\225\347\224\250\345\257\271\350\261\241.md" index fc6f989..8f77b10 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25464\351\241\271\357\274\232\351\200\232\350\277\207\346\216\245\345\217\243\345\274\225\347\224\250\345\257\271\350\261\241.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25464\351\241\271\357\274\232\351\200\232\350\277\207\346\216\245\345\217\243\345\274\225\347\224\250\345\257\271\350\261\241.md" @@ -36,5 +36,5 @@ Set sonSet = new HashSet<>();   这三种情况并不是详尽无遗的,而只是表达了一些“适合用于类来引用对象”的情形。在实践中,给定的对象是否具有适当的接口应该是很显然的。如果有,用接口引用对象就会使程序更加灵活;**如果没有合适的接口,则使用类层次接口中提供了必要功能的最基础的类** 。 -> - [第 63 项:了解字符串连接的性能](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) -> - [第 65 项:接口优先于反射机制](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) +> - [第 63 项:了解字符串连接的性能](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第63项:注意字符串拼接的性能.md) +> - [第 65 项:接口优先于反射机制](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25465\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\345\217\215\345\260\204\346\234\272\345\210\266.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25465\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\345\217\215\345\260\204\346\234\272\345\210\266.md" index 6673477..2e99895 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25465\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\345\217\215\345\260\204\346\234\272\345\210\266.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25465\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\345\217\215\345\260\204\346\234\272\345\210\266.md" @@ -67,5 +67,5 @@ private static void fatalError(String msg) {   简而言之,反射机制是一种功能强大的机制,对于复杂系统中特定的编程任务,它是非常必要的,但它也有一些缺点。如果你编写的程序必须要与编译时未知的类一起工作,如果有可能,就应该仅仅使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类。 -> - [第 64 项:通过接口引用对象](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) -> - [第 66 项:谨慎地使用本地方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) +> - [第 64 项:通过接口引用对象](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第64项:通过接口引用对象.md) +> - [第 66 项:谨慎地使用本地方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md" index 9d7c01d..75a962a 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md" @@ -12,5 +12,5 @@   总而言之,在使用本地方法之前务必三思。极少数情况下会需要使用本地方法来提高性能。如果你必须要使用本地方法来访问底层的资源,或者本地代码库,也要尽可能少用本地代码,并且要进行全面测试。本地代码中的一个 BUG 就有可能破坏整个应用程序。 -> - [第 65 项:接口优先于反射机制](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) -> - [第 67 项:谨慎地进行优化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) +> - [第 65 项:接口优先于反射机制](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第65项:接口优先于反射机制.md) +> - [第 67 项:谨慎地进行优化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25467\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\350\277\233\350\241\214\344\274\230\345\214\226.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25467\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\350\277\233\350\241\214\344\274\230\345\214\226.md" index 7920914..6847bda 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25467\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\350\277\233\350\241\214\344\274\230\345\214\226.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25467\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\350\277\233\350\241\214\344\274\230\345\214\226.md" @@ -38,5 +38,5 @@   总而言之,不要费力去编写快速的程序——应该努力编写好的程序,速度自然会随之而来。在设计系统的时候,特别是在设计 API、链路层协议和永久数据格式的时候,一定要考虑性能的因素。当构建完系统之后,要测试它的性能。如果它足够快,你的任务就完成了。如果不够快,则可以在性能剖析器的帮助下,找到问题的根源,然后设法优化系统中相关的部分。第一个步骤是检查所选择的算法:再多的底层优化也无法弥补算法的选择不当。必要时重复这个过程,在每次改变之后都要测试性能,直到满意为止。 -> - [第 66 项:谨慎地使用本地方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) -> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) +> - [第 66 项:谨慎地使用本地方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第66项:谨慎地使用本地方法.md) +> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md" index fc9711f..3462af0 100644 --- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md" +++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md" @@ -50,5 +50,5 @@ if (car.speed() > 2 * SPEED_LIMIT)   总而言之,把标准的命名惯例当作一种内在的机制来看待,并且学着用它们作为第二天性(nature)。字面惯例是非常直接和明确的;语法惯例则更复杂,也更松散。下面这句话引自《The Java Language Specification》\[JLS, 6.1\]:“如果长期养成的习惯用法与此不同,请不要盲目遵从这些命名惯例。”请运用常识。 -> - [第 67 项:谨慎地进行优化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) -> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) +> - [第 67 项:谨慎地进行优化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第67项:谨慎地进行优化.md) +> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md" index 3c1096f..b3f4baa 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md" @@ -64,5 +64,5 @@ Iterator i = collection.iterator();   总而言之,异常(exception)是为了在异常情况下使用而设计的。不要将它们用于普通的控制流,也不要编写迫使它们这么做的 API。 -> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) -> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) +> - [第 68 项:遵守普遍接受的命名惯例](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第68项:遵守普遍接受的命名惯例.md) +> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md" index 17e20e1..1deacf5 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md" @@ -22,5 +22,5 @@   总而言之,对于可恢复的情况,使用受检异常;对于程序错误,则使用运行时异常。如果不知道使用哪种【异常】的时候,就抛出未受检的异常。不要定义既不是受检异常也不是运行时异常的任何可抛出结构。在你的受检异常中提供方法来帮助恢复【程序】。 -> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) -> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) +> - [第 69 项:只针对异常的情况才使用异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第69项:只针对异常的情况才使用异常.md) +> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md" index 9e1c54a..4b3e484 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md" @@ -57,5 +57,5 @@ obj.action(args)   总之,在谨慎使用受检异常时可以提高程序的可靠性; 当过度使用时,它们会使 API 难以使用。如果调用者无法从失败的执行情况恢复,则抛出未受检异常。如果可能恢复【程序正常状态】并且你希望强制调用者处理异常情况,请首先考虑返回 optional。只有在失败的情况下提供的信息不足时才应该抛出一个受检异常。 -> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) -> - [第 72 项:优先使用标准的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) +> - [第 70 项:对可恢复的情况使用受检异常,对编程错误使用运行时异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常.md) +> - [第 72 项:优先使用标准的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md" index d0ce525..b5f64be 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md" @@ -31,5 +31,5 @@   选择要重用的异常可能很棘手,因为上表中的“使用场合”似乎并不相互排斥。例如,考虑一个表示一副纸牌的对象。假设有个处理发牌操作的方法,它的参数是一手牌的纸牌张数。假设调用者在这个参数中传递的值大于整副纸牌的剩余张数。这种情形既可以被解释为 IllegalArgumentException(handSize 参数的值太大),也可以被解释为 IllegalStateException(纸牌对象包含的纸牌太少)。在这种情况下,有个规则就是:如果没有可用的参数值,则抛出 IllegalStateException,否则抛出 IllegalArgumentException。 -> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) -> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) +> - [第 71 项:避免不必要地使用受检异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第71项:避免不必要地使用受检异常.md) +> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25473\351\241\271\357\274\232\346\212\233\345\207\272\344\270\216\346\212\275\350\261\241\347\233\270\345\257\271\345\272\224\347\232\204\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25473\351\241\271\357\274\232\346\212\233\345\207\272\344\270\216\346\212\275\350\261\241\347\233\270\345\257\271\345\272\224\347\232\204\345\274\202\345\270\270.md" index 040c5ca..26e294f 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25473\351\241\271\357\274\232\346\212\233\345\207\272\344\270\216\346\212\275\350\261\241\347\233\270\345\257\271\345\272\224\347\232\204\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25473\351\241\271\357\274\232\346\212\233\345\207\272\344\270\216\346\212\275\350\261\241\347\233\270\345\257\271\345\272\224\347\232\204\345\274\202\345\270\270.md" @@ -61,5 +61,5 @@ class HigherLevelException extends Exception {   总而言之,如果不能阻止或者处理来自更底层的异常,一般的做法是使用异常转译,除非底层方法碰巧可以保证它抛出的所有异常对高层也合适才可以将异常从底层传播到高层。异常链对高层和底层异常都提供了最佳的功能:它允许抛出适当的高层异常,同时又能捕获底层的原因进行失败分析(第 75 项)。 -> - [第 72 项:优先使用标准的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) -> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) +> - [第 72 项:优先使用标准的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第72项:优先使用标准的异常.md) +> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md" index 0986714..b4f55c9 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md" @@ -16,5 +16,5 @@   总而言之,要为你编写的每个方法所能抛出的每个异常建立文档。对于未受检的和受检的异常,以及对于抽象的和具体的方法也一样。此文档应采用 doc 注释中的@throws 标记的形式。 为每个受检异常提供单独的 throws 子句,不要为未受检的异常提供 throws 子句。如果没有为可能抛出的异常建立文档,其他人就很难或者根本不可能有效地使用你的类和接口。 -> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) -> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) +> - [第 73 项:抛出与抽象对应的异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第73项:抛出与抽象相对应的异常.md) +> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md" index 08c3dc2..5f4ada7 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md" @@ -34,5 +34,5 @@ public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {   正如第 70 项中所建议的,为捕获的异常的失败(failure-capture)的信息提供一些访问方法是合适的(在上述例子中的 lowerBound、upperBound 和 index 方法)。相对于未受检异常,未受检异常提供这样的访问方法更为重要,因为捕获失败的信息对于【将程序】从失败中恢复【正常】是非常有用的。程序猿希望通过程序的手段来访问未受检异常的细节,这很少见(尽管也是可以想象得到的)。然而,即使对于未受检的异常,作为一般原则提供这些访问方法也是明智的(第 12 项,原书 57 页)。 -> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) -> - [第 76 项:努力使失败保持原子性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) +> - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md) +> - [第 76 项:努力使失败保持原子性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25476\351\241\271\357\274\232\345\212\252\345\212\233\344\275\277\345\244\261\350\264\245\344\277\235\346\214\201\345\216\237\345\255\220\346\200\247.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25476\351\241\271\357\274\232\345\212\252\345\212\233\344\275\277\345\244\261\350\264\245\344\277\235\346\214\201\345\216\237\345\255\220\346\200\247.md" index cc36f71..9974835 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25476\351\241\271\357\274\232\345\212\252\345\212\233\344\275\277\345\244\261\350\264\245\344\277\235\346\214\201\345\216\237\345\255\220\346\200\247.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25476\351\241\271\357\274\232\345\212\252\345\212\233\344\275\277\345\244\261\350\264\245\344\277\235\346\214\201\345\216\237\345\255\220\346\200\247.md" @@ -30,6 +30,6 @@ public Object pop() {   一般而言,作为方法规范的一部分,产生的任何异常都应该让对象保持在该方法调用之前的状态。如果违反这条规则,API 文档就应该清楚地指明对象将会处于什么样的状态。遗憾的是,大量现有的 API 文档都未能做到这一点。 -> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) -> - [第 77 项:不要忽略异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) +> - [第 75 项:在细节消息中包含失败-捕获信息](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第75项:在详细信息中包含捕获的失败信息.md) +> - [第 77 项:不要忽略异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25477\351\241\271\357\274\232\344\270\215\350\246\201\345\277\275\347\225\245\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25477\351\241\271\357\274\232\344\270\215\350\246\201\345\277\275\347\225\245\345\274\202\345\270\270.md" index 5f271d1..44a90c4 100644 --- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25477\351\241\271\357\274\232\344\270\215\350\246\201\345\277\275\347\225\245\345\274\202\345\270\270.md" +++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25477\351\241\271\357\274\232\344\270\215\350\246\201\345\277\275\347\225\245\345\274\202\345\270\270.md" @@ -26,5 +26,5 @@ try {   本项中的建议同样适用于受检异常和未受检的异常。不管异常代表了可预见的异常条件,还是编程错误,用空的 catch 块忽略它,将会导致程序在遇到错误的情况下悄然地执行下去。然后,有可能在将来的某个点上,当程序不能再容忍与错误源明显相关的问题时,它就会失败。正确地处理异常能够彻底挽回失败。只要将异常传播给外界,至少会导致程序快速失败,从而保留了有助于调试该失败条件的信息。 -> - [第 76 项:努力使失败保持原子性](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) -> - [第 78 项:同步访问共享的可变数据](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) +> - [第 76 项:努力使失败保持原子性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md) +> - [第 78 项:同步访问共享的可变数据](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md" index bdd2f74..197cac3 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md" @@ -122,5 +122,5 @@ public static long generateSerialNumber() {   简而言之,**当多个线程共享可变数据的时候,每个读或者写数据的线程都必须执行同步** 。如果没有同步,就无法保证一个线程所做的修改对另一个线程是可见的。未能同步共享可变数据会造成程序的*活性和安全性失败(liveness and safety failures)*。这样的失败是最难以调试的。它们可能是间歇性的,且与时间相关,程序的行为在不同的 VM 上可能根本不同。如果只需要线程之间的交互通信,而不需要互斥,volatile 修饰符就是一种可以接受的同步形式,但要正确地使用它可能需要一些技巧。 -> - [第 77 项:不要忽略异常](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) -> - [第 79 项:避免过度同步](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) +> - [第 77 项:不要忽略异常](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第77项:不要忽略异常.md) +> - [第 79 项:避免过度同步](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25479\351\241\271\357\274\232\351\201\277\345\205\215\350\277\207\345\272\246\345\220\214\346\255\245.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25479\351\241\271\357\274\232\351\201\277\345\205\215\350\277\207\345\272\246\345\220\214\346\255\245.md" index 9ae9dd3..48a4877 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25479\351\241\271\357\274\232\351\201\277\345\205\215\350\277\207\345\272\246\345\220\214\346\255\245.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25479\351\241\271\357\274\232\351\201\277\345\205\215\350\277\207\345\272\246\345\220\214\346\255\245.md" @@ -158,5 +158,5 @@ private void notifyElementAdded(E element) {   简而言之,为了避免死锁和数据被破坏,千万不要从同步区域调用外来方法。更为一般地讲,要尽量限制同步区域内部的工作量。当你在设计一个可变类的时候,要考虑一下它们是否应该自己完成同步操作。在现在这个多核的时代,这比永远不要过度同步来得更重要。只有当你有足够的理由一定要在内部同步类的时候,才应该这么做,同时还应该将这个决定清楚地写到文档中(第 82 项)。 -> - [第 78 项:同步访问共享的可变数据](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) -> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) +> - [第 78 项:同步访问共享的可变数据](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第78项:同步访问共享的可变数据.md) +> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25480\351\241\271\357\274\232executor\343\200\201task\345\222\214stream\344\274\230\345\205\210\344\272\216\347\272\277\347\250\213.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25480\351\241\271\357\274\232executor\343\200\201task\345\222\214stream\344\274\230\345\205\210\344\272\216\347\272\277\347\250\213.md" index dd0d0f4..d31de1d 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25480\351\241\271\357\274\232executor\343\200\201task\345\222\214stream\344\274\230\345\205\210\344\272\216\347\272\277\347\250\213.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25480\351\241\271\357\274\232executor\343\200\201task\345\222\214stream\344\274\230\345\205\210\344\272\216\347\272\277\347\250\213.md" @@ -32,5 +32,5 @@ exec.shutdown();   对 Executor Framework 的完整处理超出了本书的范围,但感兴趣的读者可以参考《Java Concurrency in Practice》\[Goetz06\]。 -> - [第 79 项:避免过度同步](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) -> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) +> - [第 79 项:避免过度同步](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第79项:避免过度同步.md) +> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25481\351\241\271\357\274\232\345\271\266\345\217\221\345\267\245\345\205\267\344\274\230\345\205\210\344\272\216wait\345\222\214notify.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25481\351\241\271\357\274\232\345\271\266\345\217\221\345\267\245\345\205\267\344\274\230\345\205\210\344\272\216wait\345\222\214notify.md" index 8de7362..9a31450 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25481\351\241\271\357\274\232\345\271\266\345\217\221\345\267\245\345\205\267\344\274\230\345\205\210\344\272\216wait\345\222\214notify.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25481\351\241\271\357\274\232\345\271\266\345\217\221\345\267\245\345\205\267\344\274\230\345\205\210\344\272\216wait\345\222\214notify.md" @@ -110,5 +110,5 @@ synchronized (obj) {   简而言之,直接使用 wait 和 notify 就像用“并发汇编语言”进行编程一样,而 java.util.concurrent 则提供了更高级的语言。**没有理由在新代码中使用 wait 和 notify,即使有,也是极少的** 。如果你在维护使用了 wait 和 notify 的代码,务必确保始终是利用标准的模式从 while 循环内部调用 wait。一般情况下,你应该优先使用 notifyAll,而不是使用 notify。如果使用 notify,请一定要小心,以确保程序的活性(liveness)。 -> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) -> - [第 82 项:线程安全性的文档化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) +> - [第 80 项:executor、task 和 stream 优先于线程](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第80项:executor、task和stream优先于线程.md) +> - [第 82 项:线程安全性的文档化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25482\351\241\271\357\274\232\347\272\277\347\250\213\345\256\211\345\205\250\346\200\247\347\232\204\346\226\207\346\241\243\345\214\226.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25482\351\241\271\357\274\232\347\272\277\347\250\213\345\256\211\345\205\250\346\200\247\347\232\204\346\226\207\346\241\243\345\214\226.md" index 4a73a43..a54f682 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25482\351\241\271\357\274\232\347\272\277\347\250\213\345\256\211\345\205\250\346\200\247\347\232\204\346\226\207\346\241\243\345\214\226.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25482\351\241\271\357\274\232\347\272\277\347\250\213\345\256\211\345\205\250\346\200\247\347\232\204\346\226\207\346\241\243\345\214\226.md" @@ -60,5 +60,5 @@ public void foo() {   简而言之,每个类都应该利用字斟句酌的说明或者线程安全注解,清楚地在文档中说明它的线程安全属性。synchronized 修饰符与这个文档毫无关系。有条件的线程安全类必须在文档中指明“哪个方法调用序列需要外部同步,以及在执行这些序列的时候要获得哪把锁”。如果你编写的是无条件的线程安全类,就应该考虑使用私有锁对象来代替同步的方法。这样可以防止客户端程序和子类的同步干扰,让你能够在后续的版本中灵活地对并发控制采用更加复杂的方法。 -> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) -> - [第 83 项:慎用延迟初始化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) +> - [第 81 项:并发工具优先于 wait 和 notify](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第81项:并发工具优先于wait和notify.md) +> - [第 83 项:慎用延迟初始化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25483\351\241\271\357\274\232\346\205\216\347\224\250\345\273\266\350\277\237\345\210\235\345\247\213\345\214\226.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25483\351\241\271\357\274\232\346\205\216\347\224\250\345\273\266\350\277\237\345\210\235\345\247\213\345\214\226.md" index d970c4a..e4fec73 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25483\351\241\271\357\274\232\346\205\216\347\224\250\345\273\266\350\277\237\345\210\235\345\247\213\345\214\226.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25483\351\241\271\357\274\232\346\205\216\347\224\250\345\273\266\350\277\237\345\210\235\345\247\213\345\214\226.md" @@ -81,5 +81,5 @@ private FieldType getField() {   简而言之,大多数的域应该正常地进行初始化,而不是延迟初始化。如果为了达到性能的目标,或者为了破坏有害的初始化循环,而必须延迟初始化一个域,就可以使用合适的延迟初始化方法。对于实例域,就使用双重检查模式(double-check idiom);对于静态域,则使用 lazy initialization holder class idiom。对于可以接受重复初始化的实例域,也可以考虑使用单重检查模式(single-check idiom)。 -> - [第 82 项:线程安全性的文档化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) -> - [第 84 项:不要依赖于线程调度器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) +> - [第 82 项:线程安全性的文档化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第82项:线程安全性的文档化.md) +> - [第 84 项:不要依赖于线程调度器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25484\351\241\271\357\274\232\344\270\215\350\246\201\344\276\235\350\265\226\344\272\216\347\272\277\347\250\213\350\260\203\345\272\246\345\231\250.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25484\351\241\271\357\274\232\344\270\215\350\246\201\344\276\235\350\265\226\344\272\216\347\272\277\347\250\213\350\260\203\345\272\246\345\231\250.md" index 6251a23..2775dcb 100644 --- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25484\351\241\271\357\274\232\344\270\215\350\246\201\344\276\235\350\265\226\344\272\216\347\272\277\347\250\213\350\260\203\345\272\246\345\231\250.md" +++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25484\351\241\271\357\274\232\344\270\215\350\246\201\344\276\235\350\265\226\344\272\216\347\272\277\347\250\213\350\260\203\345\272\246\345\231\250.md" @@ -40,5 +40,5 @@ public class SlowCountDownLatch {   总之,不要让应用程序的正确性依赖于线程调度器。由此产生的程序既不健壮,也不具有可移植性。以此推出结论,不要依赖 Thread.yield 或线程优先级。这些措施仅仅是对调度器做些暗示。线程优先级可以用来提高一个已经能正常工作的程序的服务质量,但永远不应该用来“修复”一个原本就不能工作的程序。 -> - [第 83 项:慎用延迟初始化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) -> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) +> - [第 83 项:慎用延迟初始化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第83项:慎用延迟初始化.md) +> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md" index c6e11b9..9543fdb 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md" @@ -51,5 +51,5 @@ static byte[] bomb() {   总之,序列化是危险的,应该避免【序列化】。如果您从头开始设计系统,请使用跨平台的结构化数据表示,例如 JSON 或 protobuf。不要反序列化不受信任的数据。如果必须这样做,请使用对象反序列化过滤,但请注意,这不能保证阻止所有的攻击。避免编写可序列化的类。如果你必须这样做,请谨慎行事。 -> - [第 84 项:不要依赖于线程调度器](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) -> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) +> - [第 84 项:不要依赖于线程调度器](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第11章:并发/第84项:不要依赖于线程调度器.md) +> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md" index 1a3eefb..2443d5a 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md" @@ -35,5 +35,5 @@ private void readObjectNoData() throws InvalidObjectException {   总而言之,实现 Serializable 接口只是看起来很容易。除非只在受保护的环境中使用类,其中各个版本之间永远不必进行互操作,并且服务器永远不会暴露给不受信任的数据,否则实现 Serializable 接口是一个很严谨的承诺,应该认真对待。如果一个类允许继承,则需要格外小心。 -> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) -> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) +> - [第 85 项:其他方法优先于 Java 序列化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第85项:其他序列化优先于Java序列化.md) +> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25487\351\241\271\357\274\232\350\200\203\350\231\221\344\275\277\347\224\250\350\207\252\345\256\232\344\271\211\347\232\204\345\272\217\345\210\227\345\214\226\345\275\242\345\274\217.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25487\351\241\271\357\274\232\350\200\203\350\231\221\344\275\277\347\224\250\350\207\252\345\256\232\344\271\211\347\232\204\345\272\217\345\210\227\345\214\226\345\275\242\345\274\217.md" index 6636b5c..648fca8 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25487\351\241\271\357\274\232\350\200\203\350\231\221\344\275\277\347\224\250\350\207\252\345\256\232\344\271\211\347\232\204\345\272\217\345\210\227\345\214\226\345\275\242\345\274\217.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25487\351\241\271\357\274\232\350\200\203\350\231\221\344\275\277\347\224\250\350\207\252\345\256\232\344\271\211\347\232\204\345\272\217\345\210\227\345\214\226\345\275\242\345\274\217.md" @@ -142,5 +142,5 @@ private synchronized void writeObject(ObjectOutputStream s) throws IOException {   总而言之,当你决定要将一个类做成可序列化的时候(第 86 项),请仔细考虑应该采用什么样的序列化形式。之后当默认的序列化形式能够合理地描述对象的逻辑状态时,才能使用默认的序列化形式;否则就要设计一个自定义的序列化形式,通过它合理地描述对象的状态。你应该分配足够多的时间来设计类的序列化方式,就好像分配足够多的实时间来设计它的导出方法一样(第 51 项)。正如你无法在将来的版本中去掉导出的方法一样,你也不能去掉序列化形式中的域;它们必须被永久地保留下去,以确保序列化兼容性(serialization compalibility)。选择错误的序列化形式对于一个类的复杂性和性能都会有永久的负面影响。 -> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) -> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) +> - [第 86 项:谨慎地实现 Serializable 接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第86项:谨慎地实现Serializable接口.md) +> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25488\351\241\271\357\274\232\344\277\235\346\212\244\346\200\247\345\234\260\347\274\226\345\206\231readObject\346\226\271\346\263\225.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25488\351\241\271\357\274\232\344\277\235\346\212\244\346\200\247\345\234\260\347\274\226\345\206\231readObject\346\226\271\346\263\225.md" index 22a5c2d..0444d6d 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25488\351\241\271\357\274\232\344\277\235\346\212\244\346\200\247\345\234\260\347\274\226\345\206\231readObject\346\226\271\346\263\225.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25488\351\241\271\357\274\232\344\277\235\346\212\244\346\200\247\345\234\260\347\274\226\345\206\231readObject\346\226\271\346\263\225.md" @@ -176,5 +176,5 @@ Wed Nov 22 00:23:41 PST 2017 - Wed Nov 22 00:23:41 PST 2017 - 无论是直接的方式还是间接的方式,都不要调用类中任何可被覆盖的方法。 -> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) -> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) +> - [第 87 项:考虑使用自定义的序列化形式](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第87项:考虑使用自定义的序列化形式.md) +> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25489\351\241\271\357\274\232\345\257\271\344\272\216\345\256\236\344\276\213\346\216\247\345\210\266\357\274\214\346\236\232\344\270\276\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216readResolve.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25489\351\241\271\357\274\232\345\257\271\344\272\216\345\256\236\344\276\213\346\216\247\345\210\266\357\274\214\346\236\232\344\270\276\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216readResolve.md" index f79cc3a..37c7ff7 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25489\351\241\271\357\274\232\345\257\271\344\272\216\345\256\236\344\276\213\346\216\247\345\210\266\357\274\214\346\236\232\344\270\276\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216readResolve.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25489\351\241\271\357\274\232\345\257\271\344\272\216\345\256\236\344\276\213\346\216\247\345\210\266\357\274\214\346\236\232\344\270\276\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216readResolve.md" @@ -108,5 +108,5 @@ public enum Elvis {   总而言之,你应该尽可能地使用枚举类型来实施实例受控的约束条件。如果做不到,同时又需要一个即可实例化又是实例受控(instance-controlled)的类,就必须提供一个 readResolve 方法,并确保该类的所有实例域都为基本类型,或者是 transient 的。 -> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) -> - [第 90 项:考虑用序列化代理代替序列化实例](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第90项:考虑用序列化代理代替序列化实例.md) +> - [第 88 项:保护性地编写 readObject 方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第88项:保护性地编写readObject方法.md) +> - [第 90 项:考虑用序列化代理代替序列化实例](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第90项:考虑用序列化代理代替序列化实例.md) diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25490\351\241\271\357\274\232\350\200\203\350\231\221\347\224\250\345\272\217\345\210\227\345\214\226\344\273\243\347\220\206\344\273\243\346\233\277\345\272\217\345\210\227\345\214\226\345\256\236\344\276\213.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25490\351\241\271\357\274\232\350\200\203\350\231\221\347\224\250\345\272\217\345\210\227\345\214\226\344\273\243\347\220\206\344\273\243\346\233\277\345\272\217\345\210\227\345\214\226\345\256\236\344\276\213.md" index afdb3dd..8a1bdc9 100644 --- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25490\351\241\271\357\274\232\350\200\203\350\231\221\347\224\250\345\272\217\345\210\227\345\214\226\344\273\243\347\220\206\344\273\243\346\233\277\345\272\217\345\210\227\345\214\226\345\256\236\344\276\213.md" +++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25490\351\241\271\357\274\232\350\200\203\350\231\221\347\224\250\345\272\217\345\210\227\345\214\226\344\273\243\347\220\206\344\273\243\346\233\277\345\272\217\345\210\227\345\214\226\345\256\236\344\276\213.md" @@ -87,4 +87,4 @@ private static class SerializationProxy > implements Serializa   总而言之,每当你发现自己必须在一个不能被客户端扩展的类上编写 readObject 或者 writeObject 方法的时候,就应该考虑使用序列化代理模式。要想稳健地将带有重要约束条件的对象序列化时,这种模式可能是最容易的方法。 -> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/lin-mt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) +> - [第 89 项:对于实例控制,枚举类型优先于 readResolve](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第12章:序列化/第89项:对于实例控制,枚举类型优先于readResolve.md) -- Gitee From 6fd4ce3415bb488b23af42f7a4d9178025b97e80 Mon Sep 17 00:00:00 2001 From: l00263786 Date: Wed, 22 Jan 2020 17:31:31 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E9=87=8D=E7=82=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8B=E5=88=92=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...34\200\350\246\201\347\232\204\345\257\271\350\261\241.md" | 4 ++-- ...57\271\350\261\241\347\232\204\345\274\225\347\224\250.md" | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" index 4d6fdf6..6a7999e 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" @@ -1,6 +1,6 @@ ## 避免创建不需要的对象 -  一般来说,最好能重用对象而不是在每次需要的时候就创建一个相同功能的新对象。重用的方式既快速,有流行。如果对象是不可变(immutable)的(第 17 项),那么就能重复使用它。 +  一般来说,最好能重用对象而不是在每次需要的时候就创建一个相同功能的新对象。重用的方式既快速,又流行。如果对象是不可变(immutable)的(第 17 项),那么就能重复使用它。   作为一个极端的反面例子,考虑下面的语句: @@ -48,7 +48,7 @@ public class RomanNumerals {   如果经常调用的话,改进版本的 isRomanNumeral 可以显着提高性能。在我的机器上,原始版本在 8 个字符的输入字符串上需要 1.1μs,而改进版本需要 0.17μs,这是 6.5 倍的速度。不仅提高了性能,而且功能更加明了。为不可见的 Pattern 实例创建一个静态的 final 字段,我们可以给它一个名字,它比正则表达式本身更具有可读性。 -  如果初始化包含改进版本的 isRimanNumberal 方法的类时,但是从不调用该方法,则不需要初始化字段 ROMAN。在第一次调用 isRimanNumberal 方法时,可以通过延迟初始化字段(第 83 项)来消除使用时未初始化的影响,但不建议这样做。延迟初始化的做法通常都有一个情况,那就是它会把实现复杂化,从而导致无法测试它的性能改进情况。 +  如果初始化包含改进版本的 isRomanNumeral 方法的类时,但是从不调用该方法,则不需要初始化字段 ROMAN。在第一次调用 isRomanNumeral 方法时,可以通过延迟初始化字段(第 83 项)来消除使用时未初始化的影响,但不建议这样做。延迟初始化的做法通常都有一个情况,那就是它会把实现复杂化,从而导致无法测试它的性能改进情况。   当一个对象是不可变的,那么就可以安全地重用它,但是在其他情况下,它并不是那么明显,甚至违反直觉。这时候可以考虑使用适配器 \[Gamma95\],也称为视图。适配器是委托给支持对象的对象(An adapter is an object that delegates to a backing object),它提供一个备用接口。因为适配器的状态不超过其支持对象的状态,所以不需要为给定对象创建一个给定适配器的多个实例。 diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index 16ae907..f558869 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -57,7 +57,7 @@ public Object pop() {   那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序猿知道数组的非活动部分是不重要的。程序猿可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序猿就手动清空这些数组元素。 -  通常来说,只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。 +  通常来说,$\underline{只要类是自己管理内存,程序猿就应该警惕内存泄漏问题}$。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。   内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它在很长一段时间没有使用,但是却仍然留在缓存中。对于这个问题,这里有好几种解决方案。如果你正好要实现这样的缓存,只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用 WeakHashMap 代表缓存,当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap 才有用处。 -- Gitee From 6c14f14641764ba31cc59fc697c58b762574e8ff Mon Sep 17 00:00:00 2001 From: l00263786 Date: Wed, 22 Jan 2020 17:34:58 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E9=87=8D=E7=82=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8B=E5=88=92=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index f558869..d4c6b48 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -57,7 +57,7 @@ public Object pop() {   那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序猿知道数组的非活动部分是不重要的。程序猿可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序猿就手动清空这些数组元素。 -  通常来说,$\underline{只要类是自己管理内存,程序猿就应该警惕内存泄漏问题}$。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。 +  通常来说,只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。   内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它在很长一段时间没有使用,但是却仍然留在缓存中。对于这个问题,这里有好几种解决方案。如果你正好要实现这样的缓存,只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用 WeakHashMap 代表缓存,当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap 才有用处。 -- Gitee From 3fb4b36f0d8bdb388808fa6be199963bf8c5add7 Mon Sep 17 00:00:00 2001 From: tilerlgt <5645442+tilerlgt@user.noreply.gitee.com> Date: Wed, 22 Jan 2020 17:39:17 +0800 Subject: [PATCH 5/7] =?UTF-8?q?update=20=E7=AC=AC02=E7=AB=A0=EF=BC=9A?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=92=8C=E9=94=80=E6=AF=81=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?/=E7=AC=AC7=E9=A1=B9=EF=BC=9A=E6=B8=85=E9=99=A4=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E5=AF=B9=E8=B1=A1=E7=9A=84=E5=BC=95=E7=94=A8.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index d4c6b48..989a967 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -57,7 +57,7 @@ public Object pop() {   那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序猿知道数组的非活动部分是不重要的。程序猿可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序猿就手动清空这些数组元素。 -  通常来说,只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。 +  通常来说,只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。   内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它在很长一段时间没有使用,但是却仍然留在缓存中。对于这个问题,这里有好几种解决方案。如果你正好要实现这样的缓存,只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用 WeakHashMap 代表缓存,当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap 才有用处。 -- Gitee From 4db8c03338f2c37be4ec7e4ee315415aa901f216 Mon Sep 17 00:00:00 2001 From: l00263786 Date: Wed, 22 Jan 2020 18:11:31 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E5=8E=9F=E6=9D=A5?= =?UTF-8?q?=E7=9A=84=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index 989a967..548d262 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -57,7 +57,7 @@ public Object pop() {   那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序猿知道数组的非活动部分是不重要的。程序猿可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序猿就手动清空这些数组元素。 -  通常来说,只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。 +  通常来说,$\underline{只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。}$一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。   内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它在很长一段时间没有使用,但是却仍然留在缓存中。对于这个问题,这里有好几种解决方案。如果你正好要实现这样的缓存,只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用 WeakHashMap 代表缓存,当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap 才有用处。 -- Gitee From fb0521458576254cca2b049764f406027d4ecf4c Mon Sep 17 00:00:00 2001 From: l00263786 Date: Thu, 23 Jan 2020 13:47:58 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- ...236\204\351\200\240\345\207\275\346\225\260.md" | 4 ++-- ...224\250\346\236\204\345\273\272\345\231\250.md" | 6 +++--- ...276\235\350\265\226\346\263\250\345\205\245.md" | 2 +- ...246\201\347\232\204\345\257\271\350\261\241.md" | 2 +- ...261\241\347\232\204\345\274\225\347\224\250.md" | 6 +++--- ...270\205\347\251\272\346\226\271\346\263\225.md" | 6 +++--- ...\274\230\345\205\210\344\272\216try-finally.md" | 2 +- ...200\232\347\224\250\347\272\246\345\256\232.md" | 6 +++--- ...345\206\231hashCode\346\226\271\346\263\225.md" | 2 +- ...345\206\231toString\346\226\271\346\263\225.md" | 8 ++++---- ...7\216\260Comparable\346\216\245\345\217\243.md" | 2 +- ...200\247\346\234\200\345\260\217\345\214\226.md" | 4 ++-- ...235\236\345\205\254\346\234\211\345\237\237.md" | 2 +- ...200\247\346\234\200\345\260\217\345\214\226.md" | 2 +- ...205\210\344\272\216\347\273\247\346\211\277.md" | 2 +- ...246\201\346\255\242\347\273\247\346\211\277.md" | 12 ++++++------ ...272\216\346\212\275\350\261\241\347\261\273.md" | 6 +++--- ...272\216\346\240\207\347\255\276\347\261\273.md" | 2 +- ...200\203\350\231\221\346\263\233\345\236\213.md" | 2 +- ...\243\346\233\277int\345\270\270\351\207\217.md" | 2 +- ...273\243\346\233\277\345\272\217\346\225\260.md" | 2 +- ...273\243\346\233\277\344\275\215\345\237\237.md" | 2 +- ...272\217\346\225\260\347\264\242\345\274\225.md" | 6 +++--- ...221\275\345\220\215\346\250\241\345\274\217.md" | 6 +++--- ...\347\224\250Overide\346\263\250\350\247\243.md" | 4 ++-- ...0\346\205\216\344\275\277\347\224\250Stream.md" | 4 ++-- ...224\250\347\232\204\345\207\275\346\225\260.md" | 4 ++-- ...277\224\345\233\236\347\261\273\345\236\213.md" | 2 +- ...212\244\346\200\247\346\213\267\350\264\235.md" | 4 ++-- ...226\271\346\263\225\347\255\276\345\220\215.md" | 2 +- ...205\216\347\224\250\351\207\215\350\275\275.md" | 12 ++++++------ ...214\350\200\214\344\270\215\346\230\257null.md" | 2 +- ...346\205\216\350\277\224\345\233\236optional.md" | 2 +- ...226\207\346\241\243\346\263\250\351\207\212.md" | 4 ++-- ...237\237\346\234\200\345\260\217\345\214\226.md" | 2 +- ...\237\347\232\204for\345\276\252\347\216\257.md" | 2 +- ...275\277\347\224\250\347\261\273\345\272\223.md" | 14 +++++++------- ...237\272\346\234\254\347\261\273\345\236\213.md" | 2 +- ...224\250\345\255\227\347\254\246\344\270\262.md" | 2 +- ...234\254\345\234\260\346\226\271\346\263\225.md" | 2 +- ...221\275\345\220\215\346\203\257\344\276\213.md" | 2 +- ...275\277\347\224\250\345\274\202\345\270\270.md" | 2 +- ...241\214\346\227\266\345\274\202\345\270\270.md" | 2 +- ...217\227\346\243\200\345\274\202\345\270\270.md" | 10 +++++----- ...207\206\347\232\204\345\274\202\345\270\270.md" | 6 +++--- ...273\272\347\253\213\346\226\207\346\241\243.md" | 6 +++--- ...244\261\350\264\245\344\277\241\346\201\257.md" | 8 ++++---- ...217\257\345\217\230\346\225\260\346\215\256.md" | 4 ++-- ...216Java\345\272\217\345\210\227\345\214\226.md" | 2 +- ...216\260Serializable\346\216\245\345\217\243.md" | 2 +- 51 files changed, 103 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 9266a35..f697e92 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的 ### [第四章 类和接口](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口) -  类和接口是 Java 程序设计语言的核心,他们也是 Java 语言的基本抽象单元。Java 语言提供了许多强大的基本元素,供程序猿来设计类和接口。本章包含的一些指南可以帮助你充分利用这些元素,以便让你编写的类和接口可用、健壮且灵活。 +  类和接口是 Java 程序设计语言的核心,他们也是 Java 语言的基本抽象单元。Java 语言提供了许多强大的基本元素,供程序员来设计类和接口。本章包含的一些指南可以帮助你充分利用这些元素,以便让你编写的类和接口可用、健壮且灵活。 > - [第 15 项:使类和成员的可访问性最小化](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第15项:使类和成员的可访问性最小化.md) > - [第 16 项:要在公有类而非公有域中使用访问方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第04章:类和接口/第16项:在公有类中使用访问方法而非公有域.md) diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" index d2560ba..f4ccfcf 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2541\351\241\271\357\274\232\350\200\203\350\231\221\351\235\231\346\200\201\345\267\245\345\216\202\346\226\271\346\263\225\350\200\214\344\270\215\346\230\257\346\236\204\351\200\240\345\207\275\346\225\260.md" @@ -28,7 +28,7 @@ public static Boolean valueOf(boolean b) {   在 Java 8 之前,接口不能有静态方法。按照惯例,名为 Type 的接口的静态工厂方法被放置在一个不可实例化的名为 Types 的配套类(noninstantiable companion class)(第 4 项)中。例如,Java Collections Framework 有 45 个便利实现,分别提供了不可修改的集合、同步集合等等。几乎所有这些实现都通过静态工厂方法在一个不可实例化的类(java.util.Collections)中导出。所有返回对象的类都是非公有的。 -  现在的 Collections Framework API 比导出的 45 个独立的公有类的那种实现方式要小得多,每种便利的实现都对应一个类。这不仅仅减少了 API 的数量,还包括概念上的权重:程序猿必须掌握的概念的数量和难度,以便使用 API。程序猿知道返回的对象正好有其接口指定的 API,因此不需要为实现类去阅读额外的类文档。此外,这种工厂方法要求客户端通过接口而不是实现类来引用返回的对象,这通常是很好的实践方式(第 64 项)。 +  现在的 Collections Framework API 比导出的 45 个独立的公有类的那种实现方式要小得多,每种便利的实现都对应一个类。这不仅仅减少了 API 的数量,还包括概念上的权重:程序员必须掌握的概念的数量和难度,以便使用 API。程序员知道返回的对象正好有其接口指定的 API,因此不需要为实现类去阅读额外的类文档。此外,这种工厂方法要求客户端通过接口而不是实现类来引用返回的对象,这通常是很好的实践方式(第 64 项)。   从 Java 8 开始,消除了接口不能包含静态方法的限制,因此通常没有理由为接口提供不可实例化的伴随类。许多公共静态成员应该放在接口本身中。但请注意,可能仍有必要将大量实现代码放在这些静态方法后面的单独的包私有类中。这是因为 Java 8 要求接口的所有静态成员都是公共的。Java 9 允许私有静态方法,但静态字段和静态成员类的属性依然是要求是公共的。 @@ -46,7 +46,7 @@ public static Boolean valueOf(boolean b) {   服务提供者框架模式有许多变体。 例如,服务访问 API 可以向客户端返回比提供者提供的服务接口更丰富的服务接口。 这是桥接模式 \[Gamma95\] 。 依赖注入框架(第 5 项)可视为强大的服务提供者。 从 Java 6 开始,该平台包含一个通用服务提供程序框架 java.util.ServiceLoader,因此您不需要(通常不应该)自己编写(第 59 项)。 JDBC 不使用 ServiceLoader,因为前者早于后者。 -  **静态工厂方法的主要限制在于,类如果不含公有的或者受保护的构造器,就不能被子类化。** 例如:不可能将 Collections Framework 中的任何方便的实现类子类化。但是这也许会因祸得福,因为它鼓励程序猿使用组合,而不是继承(第 18 项),并且要求必须是不可变的(第 17 项)。 +  **静态工厂方法的主要限制在于,类如果不含公有的或者受保护的构造器,就不能被子类化。** 例如:不可能将 Collections Framework 中的任何方便的实现类子类化。但是这也许会因祸得福,因为它鼓励程序员使用组合,而不是继承(第 18 项),并且要求必须是不可变的(第 17 项)。   **静态工厂方法的第二个缺点是程序员很难找到它们。** 它们不像构造函数那样在 API 文档中脱颖而出,因此很难弄清楚如何实例化提供静态工厂方法而不是构造函数的类。 Javadoc 工具有一天可能会引起对静态工厂方法的注意。 在此期间,您可以通过引起对类或接口文档中的静态工厂的注意并遵守常见的命名约定来减少此问题。 以下是静态工厂方法的一些常用名称。 这份清单远非详尽无遗: diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" index 029676c..4969b6e 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2542\351\241\271\357\274\232\345\275\223\351\235\242\344\270\264\345\244\232\344\270\252\345\217\202\346\225\260\347\232\204\346\236\204\351\200\240\345\231\250\346\227\266\350\200\203\350\231\221\344\275\277\347\224\250\346\236\204\345\273\272\345\231\250.md" @@ -2,7 +2,7 @@   静态工厂和构造器有个共同的局限性:他们都不能很好地扩展到大量的可选参数。考虑用一个类表示包装食品外面显示的营养成分标签。这些标签中有几个域是必需的:每份的含量、每罐的含量以及每份的卡路里,还有超过 20 个可选域:总脂肪、饱和脂肪量、转化脂肪、胆固醇、钠等等。大多数产品在某几个可选域中都会有非零的值。 -  对于这样的类,应该采用哪种构造器或者静态方法来编写呢?程序猿一向习惯采用重叠构造器(telescoping constructor)模式,在这种模式下,提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,以此类推,最后一个构造器包含所有可选参数。下面有个示例,为了简单起见,它显示四个可选域: +  对于这样的类,应该采用哪种构造器或者静态方法来编写呢?程序员一向习惯采用重叠构造器(telescoping constructor)模式,在这种模式下,提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,以此类推,最后一个构造器包含所有可选参数。下面有个示例,为了简单起见,它显示四个可选域: ```java // Telescoping constructor pattern - does not scale well! @@ -79,9 +79,9 @@ cocaCola.setSodium(35); cocaCola.setCarbohydrate(27); ``` -  遗憾的是,这种 JavaBean 模式自身有很严重的缺点。因为构造过程被分到了几个调用中,在构造的过程中 JavaBean 可能处于不一致的状态。类无法通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来十分困难。与此相关的另一点不足在于,JavaBean 模式阻止了把类做成了不可变的可能(第 17 项),这就需要程序猿付出额外的努力来保证它的线程安全。 +  遗憾的是,这种 JavaBean 模式自身有很严重的缺点。因为构造过程被分到了几个调用中,在构造的过程中 JavaBean 可能处于不一致的状态。类无法通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来十分困难。与此相关的另一点不足在于,JavaBean 模式阻止了把类做成了不可变的可能(第 17 项),这就需要程序员付出额外的努力来保证它的线程安全。 -  在构造器完成构造对象之前进行加锁,完成构造之后进行解锁,这就能弥补以上的不足之处,但是这种方式十分笨拙,在实践中很少使用。此外,它甚至会在运行时出现错误,因为编译器无法确保程序猿会在使用构造器之前进行加锁操作。 +  在构造器完成构造对象之前进行加锁,完成构造之后进行解锁,这就能弥补以上的不足之处,但是这种方式十分笨拙,在实践中很少使用。此外,它甚至会在运行时出现错误,因为编译器无法确保程序员会在使用构造器之前进行加锁操作。   幸运的是,还有第三种替代方法,结合了重叠构造器的安全性和 JavaBean 模式的可读性。这就是 Builder 模式 \[Gamma95\] 的一种形式。不直接生成想要的对象,而是让客户端调用一个带有所有必需参数的构造器方法(或者静态工厂方法)去获得一个 builder 对象,然后客户端在`builder`对象上调用类似于 setter 的方法来设置每个相关的可选参数。最后,客户端调用无参的`build`方法来生成不可变的对象。这个`builder`通常是它构建的类的静态成员类(第 24 项)。下面就是它的示例: diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" index 96bc75c..b0f9e54 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2545\351\241\271\357\274\232\345\233\272\345\256\232\350\265\204\346\272\220\351\246\226\351\200\211\344\275\277\347\224\250\344\276\235\350\265\226\346\263\250\345\205\245.md" @@ -43,7 +43,7 @@ public class SpellChecker { } ``` -  这种依赖注入很简单,以至于程序猿用了很多年却不知道它有一个名称。虽然我们的拼写检查器只有一个资源(字典),但是依赖注入可以使用任意数量的资源和任意的依赖关系,它保留了不变性(第 17 项),因此多个客户端可以共享依赖对象(假设客户端需要相同的底层资源)。依赖注入同样适用于构造函数、静态工厂(第 1 项)和构建器(第 2 项)。 +  这种依赖注入很简单,以至于程序员用了很多年却不知道它有一个名称。虽然我们的拼写检查器只有一个资源(字典),但是依赖注入可以使用任意数量的资源和任意的依赖关系,它保留了不变性(第 17 项),因此多个客户端可以共享依赖对象(假设客户端需要相同的底层资源)。依赖注入同样适用于构造函数、静态工厂(第 1 项)和构建器(第 2 项)。   将资源工厂传递给构造函数就会变成一个有用的模式。工厂是一个对象,通过重复调用这个工厂可以创建某个类型的实例对象。这些就是工厂方法模式 \[Gamma95\]。Java 8 中引入的 Supplier <T>接口非常适合体现工厂。在输入上采用 Supplier <T>的方法通常应该使用泛型(第 31 项)约束工厂的类型参数,以允许客户端传入创建指定类型的任何子类型的工厂。例如,这是一种使用客户提供的工厂生成马赛克来生成每个图块的方法: diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" index 6a7999e..56a469b 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2546\351\241\271\357\274\232\351\201\277\345\205\215\345\210\233\345\273\272\344\270\215\351\234\200\350\246\201\347\232\204\345\257\271\350\261\241.md" @@ -54,7 +54,7 @@ public class RomanNumerals {   例如,Map 接口的 keySet 方法返回 Map 对象的 Set 视图,该视图由 Map 中的所有键组成。看起来,似乎每次调用 keySet 都必须创建一个新的 Set 实例,但是对给定 Map 对象上的 keySet 的每次调用都可能返回相同的 Set 实例。尽管返回的 Set 实例通常是可变的,但所有返回的对象在功能上都是相同的:当其中一个返回的对象发生更改时,所有其他对象也会发生更改,因为它们都由相同的 Map 实例支持。虽然创建 keySet 视图对象的多个实例在很大程度上是无害的,但不必要这样做,并且这样做没有任何好处。 -  创建不必要的对象的另一种方式是自动装箱,它允许程序猿将基本类型和装箱基本类型(Boxed Primitive Type)混用,按需自动装箱和拆箱。自动装箱使得基本类型和装箱基本类型之间的差别变得模糊起来,但是并没有完全消除。它们在语义上还有微妙的差别,在性能上也有着比较明显的差别(第 61 项)。请考虑以下方法,该方法计算所有正整数值的总和,为此,程序必须使用 long 类型,因为 int 类型无法容纳所有正整数的总和: +  创建不必要的对象的另一种方式是自动装箱,它允许程序员将基本类型和装箱基本类型(Boxed Primitive Type)混用,按需自动装箱和拆箱。自动装箱使得基本类型和装箱基本类型之间的差别变得模糊起来,但是并没有完全消除。它们在语义上还有微妙的差别,在性能上也有着比较明显的差别(第 61 项)。请考虑以下方法,该方法计算所有正整数值的总和,为此,程序必须使用 long 类型,因为 int 类型无法容纳所有正整数的总和: ```java // Hideously slow! Can you spot the object creation? diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" index 548d262..991dd44 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2547\351\241\271\357\274\232\346\270\205\351\231\244\350\277\207\346\234\237\345\257\271\350\261\241\347\232\204\345\274\225\347\224\250.md" @@ -1,6 +1,6 @@ ## 清除过期对象的引用 -  当你从手工管理内存的语言(比如 C 或者 C++)转换到具有垃圾回收功能的语言的时候,程序猿的工作就会变得更加容易,因为当你用完了对象之后,他们就会被自动回收。当你第一次经历对象回收功能的时候,会觉得这简直有点不可思议。这很容易给你留下这样的印象,认为自己不再需要考虑内存管理的事情了,其实不然。 +  当你从手工管理内存的语言(比如 C 或者 C++)转换到具有垃圾回收功能的语言的时候,程序员的工作就会变得更加容易,因为当你用完了对象之后,他们就会被自动回收。当你第一次经历对象回收功能的时候,会觉得这简直有点不可思议。这很容易给你留下这样的印象,认为自己不再需要考虑内存管理的事情了,其实不然。   考虑下面这个简单的栈实现的例子: @@ -55,9 +55,9 @@ public Object pop() {   当程序员第一次被类似这样的问题困扰的时候,它们往往会过分小心:对于每一个对象的引用,一旦程序不再用到它,就把它清空。其实这样做即没必要,也不是我们所期望的,因为这样做会把程序代码弄得很乱。清空对象引用应该是一种例外,而不是一种规范行为。消除过期引用最好的方法是让包含该引用的变量结束其生命周期。如果你是在最紧凑的作用域范围内定义每一个变量(第 57 项),这种情形就会自然而然地发生。 -  那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序猿知道数组的非活动部分是不重要的。程序猿可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序猿就手动清空这些数组元素。 +  那么,何时应该清空引用呢?Stack 类的哪方面特性使它易于遭受内存泄漏的影响呢?简而言之,问题在于,Stack 类自己管理内存(manage its own memory)、存储池(storage pool)包含了 elements 数组(对象引用单元,而不是对象本身)的元素。数组活动区域(同前面的定义)中的元素是已分配的(allocated),而数组其余部分的元素则是自由的(free)。但是垃圾回收器无法知道这一点;对于垃圾回收器而言,elements 数组中的所有对象引用都同等有效。只有程序员知道数组的非活动部分是不重要的。程序员可以把这个情况告知垃圾回收器,做法很简单:一旦数组元素变成了非活动部分的一部分,程序员就手动清空这些数组元素。 -  通常来说,$\underline{只要类是自己管理内存,程序猿就应该警惕内存泄漏问题。}$一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。 +  通常来说,$\underline{只要类是自己管理内存,程序员就应该警惕内存泄漏问题。}$一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。   内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它在很长一段时间没有使用,但是却仍然留在缓存中。对于这个问题,这里有好几种解决方案。如果你正好要实现这样的缓存,只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用 WeakHashMap 代表缓存,当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap 才有用处。 diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" index edccb49..f587c53 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2548\351\241\271\357\274\232\351\201\277\345\205\215\344\275\277\347\224\250\347\273\210\347\273\223\346\226\271\346\263\225\345\222\214\346\270\205\347\251\272\346\226\271\346\263\225.md" @@ -5,11 +5,11 @@   提醒 C ++程序员不要将终结方法或清理方法视为 Java 的 C ++析构函数的类比。 在 C ++中,析构函数是回收与对象关联的资源的常用方法,对象是构造函数的必要对应物。 在 Java 中,当一个对象无法访问时,垃圾回收器会回收与对象相关联的内存,而不需要程序员的特别处理(requiring no special effort on the part of the programmer)。C++的析构函数也可以被用来回收其他的非内存资源。在 Java 中,使用 try-with-resources 或者 try-finally 块来完成这个目的。 -  终结方法或者清理方法的缺点在于不能保证会被及时地执行\[JLS, 12.6\]。从一个对象变得不可达开始,到它的终结方法或清理方法被执行,所花费的这段时间是任意长的(也就是说我们无法预知一个对象在销毁之后和执行终结方法和清理方法之间的间隔时间)。这意味着,对时间有严格要求(time-critical)的任务不应该由终结方法或清理方法来完成。例如,用中介方法来关闭已经打开的文件,这是严重的错误,因为打开文件的描述符是一种有限的资源。如果由于系统在运行终结方法或清理方法时延迟而导致许多文件处于打开状态,则程序可能会因为无法再打开文件而运行失败。 +  终结方法或者清理方法的缺点在于不能保证会被及时地执行\[JLS, 12.6\]。从一个对象变得不可达开始,到它的终结方法或清理方法被执行,所花费的这段时间是任意长的(也就是说我们无法预知一个对象在销毁之后和执行终结方法和清理方法之间的间隔时间)。这意味着,对时间有严格要求(time-critical)的任务不应该由终结方法或清理方法来完成。例如,用终结方法来关闭已经打开的文件,这是严重的错误,因为打开文件的描述符是一种有限的资源。如果由于系统在运行终结方法或清理方法时延迟而导致许多文件处于打开状态,则程序可能会因为无法再打开文件而运行失败。   执行终结算法和清除方法的及时性主要取决于垃圾回收算法,垃圾回收算法在不同的 JVM 实现中大相径庭。如果程序依赖于终结方法或清理方法被执行的时间点,这个程序可能在你测试它的 JVM 上完美运行,然而在你最重要客户的 JVM 平台上却运行失败,这完全是有可能的。 -  延迟终结过程并不只是一个理论问题。为类提供终结方法可以延迟其实例的回收过程。一位同事在调试一个长期运行的 GUI 应用程序的时候,该应用程序莫名其妙地出现 OutOfMemoryError 错误而死亡。分析表明,该应用程序死亡的时候,其终结方法队列中有数千个图形对象正在等待被回收和终结。遗憾的是,终结方法所在的线程优先级比应用程序其他线程的要低得多,所以对象没有在符合回收条件的时候及时被回收( so objects were not getting finalized at the rate they became eligible for finalization)。语言规范并不保证哪个线程将会执行终结方法,所以,除了避免使用中介方法之外,并没有很轻便的办法能够避免这样的问题。在这方面,清理方法比终结方法要好一些,因为类的创建者可以控制他们自己的清理线程,但是清理方法仍然是在后台运行,还是在垃圾收集器的控制下,因此无法保证及时清理。 +  延迟终结过程并不只是一个理论问题。为类提供终结方法可以延迟其实例的回收过程。一位同事在调试一个长期运行的 GUI 应用程序的时候,该应用程序莫名其妙地出现 OutOfMemoryError 错误而死亡。分析表明,该应用程序死亡的时候,其终结方法队列中有数千个图形对象正在等待被回收和终结。遗憾的是,终结方法所在的线程优先级比应用程序其他线程的要低得多,所以对象没有在符合回收条件的时候及时被回收( so objects were not getting finalized at the rate they became eligible for finalization)。语言规范并不保证哪个线程将会执行终结方法,所以,除了避免使用终结方法之外,并没有很轻便的办法能够避免这样的问题。在这方面,清理方法比终结方法要好一些,因为类的创建者可以控制他们自己的清理线程,但是清理方法仍然是在后台运行,还是在垃圾收集器的控制下,因此无法保证及时清理。   语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。当一个程序终止的时候,某些已经无法访问的对象上的终结方法却根本没有被执行,这完全是有可能的。因此,你不应该依赖终结方法或者清理方法来更新重要的持久状态。例如,依赖终结方法或者清理方法来释放共享资源(比如数据库)上的永久锁,很容易让整个分布式系统垮掉。 @@ -19,7 +19,7 @@   使用终结方法和清理方法会严重影响性能。在我的机器上,创建一个简单的 AutoCloseable 对象,使用 try-with-resources 关闭它,并让垃圾收集器回收它的时间大约是 12 ns。使用终结方法之后时间增加到 550ns。换句话说,用终结方法创建和销毁对象慢了大约 50 倍。这主要是因为终结器会抑制有效的垃圾收集。如下所述,如果你使用清洁方法或终结方法去清理类的所有实例,清理方法和终结方法的速度是差不多的(在我的机器上每个实例大约 500ns),但是如果你只是把这两个方法作为安全保障(safety net)的话,清理方法比终结方法快很多。在这种情况下,在我的机器上创建,清理 d 和销毁一个对象大约需要 66 ns,这意味着如果你不适用它,你需要支付五倍(而不是五十)安全保障的费用(which means you pay a factor of five (not fifty) for the insurance of a safety net if you don’t use it)。 -  终结方法有一个很严重的安全问题:它们会打开你的类直到终结方法对其进行攻击(they open your class up to finalizer attacks)。使用终结方法进行攻击的原理很简单(The idea behind a finalizer attack is simple):如果从构造方法或将其序列化的等价方法(readObject 和 readResolve[第 12 章])中抛出异常,恶意子类的终结方法可以在部分构造的对象上运行,这些对象应该“死在藤上(died on the vine)”。这些终结方法可以在一个静态域上记录下这些对象的引用,保护它们不被垃圾回收器回收。一旦这些异常的对象呗记录下来,在这个对象上调用任意方法是一件简单的事情,这些方法本来就不应该被允许存在。从构造函数中抛出异常应足以防止对象的创建,在终结方法中,事实并非如此(Throwing an exception from a constructor should be sufficient to prevent an object from coming into existence; in the presence of finalizers, it is not)。这种攻击会产生可怕的后果。final 修饰的类不会受到终结方法的攻击,因为没人可以编写 final 类的恶意子类。要保护非 final 类受到终结方法的攻击,请编写一个不执行任何操作的 final finalize 方法。 +  终结方法有一个很严重的安全问题:它们会打开你的类直到终结方法对其进行攻击(they open your class up to finalizer attacks)。使用终结方法进行攻击的原理很简单(The idea behind a finalizer attack is simple):如果从构造方法或将其序列化的等价方法(readObject 和 readResolve[第 12 章])中抛出异常,恶意子类的终结方法可以在部分构造的对象上运行,这些对象应该“死在藤上(died on the vine)”。这些终结方法可以在一个静态域上记录下这些对象的引用,保护它们不被垃圾回收器回收。一旦这些异常的对象被记录下来,在这个对象上调用任意方法是一件简单的事情,这些方法本来就不应该被允许存在。从构造函数中抛出异常应足以防止对象的创建,在终结方法中,事实并非如此(Throwing an exception from a constructor should be sufficient to prevent an object from coming into existence; in the presence of finalizers, it is not)。这种攻击会产生可怕的后果。final 修饰的类不会受到终结方法的攻击,因为没人可以编写 final 类的恶意子类。要保护非 final 类受到终结方法的攻击,请编写一个不执行任何操作的 final finalize 方法。   某些类(比如文件或线程)封装了需要终止的资源,对于这些类的对象,你应该用什么方法来替代终结方法和清理方法呢?(So what should you do instead of writing a finalizer or cleaner for a class whose objects encapsulate resources that require termination, such as files or threads?)对于这些类,你只需要让其实现`AutoCloseable`接口,并要求其客户端在每个实例不再需要的时候调用实例上的`close`方法,通常使用 try-with-resources 来确保即使出现异常时资源也会被终止(第 9 项)。值得一提的一个细节是实例必须跟踪其本身是否已被关闭:`close`方法必须在一个字段中记录这个实例已经无效,而其他方法必须检查此字段并抛出 IllegalStateException(如果其他方法在实例关闭之后被调用)。 diff --git "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" index c31d97e..50c7637 100644 --- "a/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" +++ "b/\347\254\25402\347\253\240\357\274\232\345\210\233\345\273\272\345\222\214\351\224\200\346\257\201\345\257\271\350\261\241/\347\254\2549\351\241\271\357\274\232try-with-resources\344\274\230\345\205\210\344\272\216try-finally.md" @@ -88,4 +88,4 @@ static String firstLineOfFile(String path, String defaultVal) {   这里经验教训是很明确的(The lesson is clear):在处理必须关闭的资源时,相比于 try-finally,始终优先使用 try-with-resources。 生成的代码更短更清晰,它生成的异常更有用。 try-with-resources 语句可以在使用必须关闭的资源的同同时轻松编写正确的代码,使用 try-finally 几乎是不可能的。 > - [第 8 项:避免使用终结方法和清除方法](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第02章:创建和销毁对象/第8项:避免使用终结方法和清空方法.md) -> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/重写equals时请遵守通用约定.md) +> - [第 10 项:覆盖 equals 时请遵守通用约定](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第03章:对于所有对象都通用的方法/第10项:重写equals时请遵守通用约定.md) diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" index d2e6cf6..232eefb 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25410\351\241\271\357\274\232\351\207\215\345\206\231equals\346\227\266\350\257\267\351\201\265\345\256\210\351\200\232\347\224\250\347\272\246\345\256\232.md" @@ -16,7 +16,7 @@ } ``` -  那么什么时候重写 equals 方法才是合适的呢?当一个类具有逻辑相等的概念时(不同于对象本身相同的概念),而超类还没有重写 equals。 这通常是“值类(value class)”的情况。 值类指的是只表示值的类,例如 Integer 或 String。程序猿在利用 equals 方法来比较对象的引用时,希望知道它们在逻辑上是否相等,而不是像了解它们是否引用了相同的对象。为了满足程序猿的需求,不仅必须重写 equals 方法,而且这样做也使得这个类的实例可以被用作映射表(map)的键(key),或者集合(set)的元素,使映射或者集合表现出预期的行为。 +  那么什么时候重写 equals 方法才是合适的呢?当一个类具有逻辑相等的概念时(不同于对象本身相同的概念),而超类还没有重写 equals。 这通常是“值类(value class)”的情况。 值类指的是只表示值的类,例如 Integer 或 String。程序员在利用 equals 方法来比较对象的引用时,希望知道它们在逻辑上是否相等,而不是像了解它们是否引用了相同的对象。为了满足程序员的需求,不仅必须重写 equals 方法,而且这样做也使得这个类的实例可以被用作映射表(map)的键(key),或者集合(set)的元素,使映射或者集合表现出预期的行为。   有一种“值类”不需要重写 equals 方法,即用实例受控(第 1 项)确保“每个值之多只存在一个对象”的类【单例模式】。枚举类型(第 34 项)就属于这种类。对于这样的类而言,逻辑相同与对象等同是一回事,因此 Object 的 equals 方法等同于逻辑意义上的 equals 方法。 @@ -229,7 +229,7 @@ public class ColorPoint { } ``` -  在 Java 平台类库中,有一些类扩展了可实例化的类,并添加了新的值组件。例如,java.sql.Timestamp 对 java.util.Date 进行了扩展,并增加了 nanoseconds 字段。Timestamp 的 equals 实现却是违反了对称性,如果 Timestamp 和 Date 对象被用于同一个集合中,或者以其他方式被混合在一起,则会引起不正确的行为。Timestamp 类有一个免责声明,告诫程序猿不要混合使用 Date 和 Timestamp 对象。只要你不把它们混合在一起,就不会有麻烦,除此之外没有其他的措施可以防止你这么做,而且结果导致的错误将很难调试。Timestamp 类的这种行为是个错误,不值得效仿。 +  在 Java 平台类库中,有一些类扩展了可实例化的类,并添加了新的值组件。例如,java.sql.Timestamp 对 java.util.Date 进行了扩展,并增加了 nanoseconds 字段。Timestamp 的 equals 实现却是违反了对称性,如果 Timestamp 和 Date 对象被用于同一个集合中,或者以其他方式被混合在一起,则会引起不正确的行为。Timestamp 类有一个免责声明,告诫程序员不要混合使用 Date 和 Timestamp 对象。只要你不把它们混合在一起,就不会有麻烦,除此之外没有其他的措施可以防止你这么做,而且结果导致的错误将很难调试。Timestamp 类的这种行为是个错误,不值得效仿。   注意,你可以在一个抽象(abstrace)类的子类中增加新的值组件,而不会违反 equals 约定。这对于类层次结构很重要,您可以通过遵循第 23 项中的建议“用类层次(class hierarchies)代替标签类(tagged classes)”来获得类层次结构。例如,你可能有一个抽象的 Shap 类,它没有任何值组件,Circle 子类添加了一个 radius 字段,Rectangle 子类添加了 length 和 width 字段。只要不可能直接创建超类的实例,前面所述的种种问题就都不会发生。 @@ -309,7 +309,7 @@ public final class PhoneNumber { - **重写 equals 方法时总要重写 hashCode 方法(第 11 项)。** - **不要企图让 equals 方法过于智能。** 如果只是简单地测试域中的值是否相等,则不难做到遵守 equals 约定。如果想过度地去寻求各种等价关系,则很容易陷入麻烦之中。把任何任何一种别名形式考虑到等价的范围内,往往是一个坏主意。例如,File 类不应该试图把指向同一个文件的符号链接(symbolic link)当做相等的对象来看待。所幸 File 类没有这样做。 -- **不要将 equals 声明中的 Object 对象替换为其他的类型。** 程序猿编写出下面这样的 equals 方法并不少见,这会使程序猿花上数小时都搞不清为什么它不能正常工作: +- **不要将 equals 声明中的 Object 对象替换为其他的类型。** 程序员编写出下面这样的 equals 方法并不少见,这会使程序员花上数小时都搞不清为什么它不能正常工作: ```java // Broken - parameter type must be Object! diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" index f65b357..f9daa98 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25411\351\241\271\357\274\232\345\275\223\351\207\215\345\206\231equals\346\226\271\346\263\225\346\230\257\345\247\213\347\273\210\351\207\215\345\206\231hashCode\346\226\271\346\263\225.md" @@ -6,7 +6,7 @@ - 如果两个对象调用 equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的 hashCode 方法都必须产生相同的整数结果。 -- 如果两个对象根据 equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的 hashCode 方法,则不一定要产生不同的结果。无论如何,程序猿应该知道,不相等的对象产生截然不同的结果,有可能提高散列表(hash tables)的性能。 +- 如果两个对象根据 equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的 hashCode 方法,则不一定要产生不同的结果。无论如何,程序员应该知道,不相等的对象产生截然不同的结果,有可能提高散列表(hash tables)的性能。   因没有覆盖 hashCode 而违反第二条的关键约定:相等的对象必须具有相等的散列码(hash code)。根据类的 equals 方法,两个截然不同的实例在逻辑上有可能是相等的,但是,根据 Object 的 hashCode 方法,它们仅仅是两个没有任何共同之处的对象。因此,Object 的 hashCode 方法返回两个看起来像是随机的整数,而不是根据通用约定所要求的那样,返回两个相等的整数。 diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" index c5a8a76..681ec51 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25412\351\241\271\357\274\232\345\247\213\347\273\210\351\207\215\345\206\231toString\346\226\271\346\263\225.md" @@ -10,7 +10,7 @@ System.out.println("Failed to connect to " + phoneNumber); ``` -  不管是否重写了 toString 方法,程序猿都将以这种方式来产生诊断信息,但是如果没有重写 toString 方法,产生的信息就没什么用。提供好的 toString 方法,不仅有益于这个类的实例,同样也有益于那些包含这些实例的引用对象,特别是集合对象。打印 Map 时有下面这两条消息:`{Jenny=PhoneNumber@163b91}`和`{Jenny=707-867-5309}`你更愿意看到哪个? +  不管是否重写了 toString 方法,程序员都将以这种方式来产生诊断信息,但是如果没有重写 toString 方法,产生的信息就没什么用。提供好的 toString 方法,不仅有益于这个类的实例,同样也有益于那些包含这些实例的引用对象,特别是集合对象。打印 Map 时有下面这两条消息:`{Jenny=PhoneNumber@163b91}`和`{Jenny=707-867-5309}`你更愿意看到哪个?   **在实际应用中,toString 方法应该返回对象中包含的所有值得关注的信息,** 比如上述电话号码例子那样。如果对象太大,或者对象中包含的状态信息难以用字符串来表达,这样做就有点不切实际。在这种情况下,toString 应该返回一个摘要信息,例如`Manhattan residential phone directory (1487536 listings)`或者`Thread[main,5,main]`。理想情况下,字符串应该是不言自明的。(Thread 例子不满足这样的要求。)如果未能在其字符串表示中包含所有对象感兴趣的信息,那么特别恼人的惩罚是测试失败报告如下所示: @@ -20,7 +20,7 @@ Assertion failure: expected {abc, 123}, but was {abc, 123}.   在实现 toString 的时候,必须做出一个很重要的决定:是否在文档中指定返回值的格式。对于值类(value class)【比较关注数值的类】,比如电话号码、矩阵之类的,就推荐这么做。指定格式的好处是,它可以被用作一种标准的、明确的适合人们阅读的对象表示法。这种表示法可以用于输入和输出,以及用在将对象持久化成人们可阅读的表现方式(This representation can be used for input and output and in persistent human-readable data objects),例如 CVS 文件。如果指定格式,通常最好提供匹配的静态工厂或构造函数,以便程序员可以轻松地在对象及其字符串表示之间来回转换。 Java 平台库中的许多值类都采用了这种方法,包括 BigInteger,BigDecimal 和大多数基本类型的包装类(boxed primitive classes)。 -  指定 toString 返回值的格式也有不足之处:如果这个类已经被广泛使用,一旦指定格式,就必须始终如一地坚持这种格式。程序猿将会编写出相应的代码来解析这种字符串的表示方法、生成这种字符串的表示方法【程序猿会编写出怎么解析我们生成的指定格式的字符串、怎么生成我们指定格式的字符串的方法】,并将其嵌入到持久化的数据中。如果将来的发行版本中改变了表示形式,那么您减将破坏其代码和数据,他们当然会抱怨。如果不指定格式,就可以保留灵活性,便于在将来的发行版本中添加信息,或者改进格式。 +  指定 toString 返回值的格式也有不足之处:如果这个类已经被广泛使用,一旦指定格式,就必须始终如一地坚持这种格式。程序员将会编写出相应的代码来解析这种字符串的表示方法、生成这种字符串的表示方法【程序员会编写出怎么解析我们生成的指定格式的字符串、怎么生成我们指定格式的字符串的方法】,并将其嵌入到持久化的数据中。如果将来的发行版本中改变了表示形式,那么您减将破坏其代码和数据,他们当然会抱怨。如果不指定格式,就可以保留灵活性,便于在将来的发行版本中添加信息,或者改进格式。   **无论你是否决定指定格式,都应该在文档中明确表明你的意图。** 如果你要指定格式,你应该严格地这样去做。例如,这里有一个第 11 项中 PhoneNumber 类的 toString 方法: @@ -55,9 +55,9 @@ Assertion failure: expected {abc, 123}, but was {abc, 123}. @Override public String toString() { ... } ``` -  在阅读这段注释之后,对于那些依赖于格式的细节进行编程或者产生持久化数据的程序猿,则只能自己承担后果。 +  在阅读这段注释之后,对于那些依赖于格式的细节进行编程或者产生持久化数据的程序员,则只能自己承担后果。 -  无论是否指定格式,**都为 toString 返回值中包含的所有信息,提供一种编程式的访问路径。** 例如,PhoneNumber 类应该包含针对 area code、prefix 和 line number 的访问方法。如果不这么做,就会迫使那些需要这些信息的程序猿不得不自己去解析这些字符串。除了降低了程序的性能,使得程序猿们去做这些不必要的工作之外,如果你改变格式的话,这个解析过程也是很容易出错的,会导致系统崩溃。如果没有提供这些访问方法,即使你已经指明了字符串的格式是可以变化的,这个字符串格式也成了事实上的 API(By failing to provide accessors, you turn the string format into a de facto API, even if you’ve specified that it’s subject to change.)。 +  无论是否指定格式,**都为 toString 返回值中包含的所有信息,提供一种编程式的访问路径。** 例如,PhoneNumber 类应该包含针对 area code、prefix 和 line number 的访问方法。如果不这么做,就会迫使那些需要这些信息的程序员不得不自己去解析这些字符串。除了降低了程序的性能,使得程序员们去做这些不必要的工作之外,如果你改变格式的话,这个解析过程也是很容易出错的,会导致系统崩溃。如果没有提供这些访问方法,即使你已经指明了字符串的格式是可以变化的,这个字符串格式也成了事实上的 API(By failing to provide accessors, you turn the string format into a de facto API, even if you’ve specified that it’s subject to change.)。   在静态实用程序类中编写 toString 方法是没有意义的(第 4 项)。你也不应该在大多数枚举类型(第 34 项)中编写 toString 方法,因为 Java 为你提供了一个非常好的方法。但是,您应该在任何抽象类中编写 toString 方法,其子类共享一个公共字符串的表示形式。例如,大多数集合实现的 toString 方法都是从抽象集合类继承的。 diff --git "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" index 72b1031..daa5898 100644 --- "a/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" +++ "b/\347\254\25403\347\253\240\357\274\232\345\257\271\344\272\216\346\211\200\346\234\211\345\257\271\350\261\241\351\203\275\351\200\232\347\224\250\347\232\204\346\226\271\346\263\225/\347\254\25414\351\241\271\357\274\232\350\200\203\350\231\221\345\256\236\347\216\260Comparable\346\216\245\345\217\243.md" @@ -85,7 +85,7 @@ public int compareTo(PhoneNumber pn) { } ``` -  在 Java 8 中,Comparator 接口配备了一组比较器构造方法,可以精确构建比较器。然后,可以使用这些比较器来实现 compareTo 方法,这是 Comparable 接口所要求的。许多程序猿更喜欢这种方法的简洁性,尽管它的性能成本很低:在我的机器上排序 PhoneNumber 实例的数组大约慢 10%。使用这种方法时,考虑使用 Java 的静态导入功能,这样您就可以通过简单的名称来引用静态比较器构造方法,以获得清晰和简洁【代码】。这就是 PhoneNumber 的 compareTo 方法看起来是如何使用这种方法: +  在 Java 8 中,Comparator 接口配备了一组比较器构造方法,可以精确构建比较器。然后,可以使用这些比较器来实现 compareTo 方法,这是 Comparable 接口所要求的。许多程序员更喜欢这种方法的简洁性,尽管它的性能成本很低:在我的机器上排序 PhoneNumber 实例的数组大约慢 10%。使用这种方法时,考虑使用 Java 的静态导入功能,这样您就可以通过简单的名称来引用静态比较器构造方法,以获得清晰和简洁【代码】。这就是 PhoneNumber 的 compareTo 方法看起来是如何使用这种方法: ```java // Comparable with comparator construction methods diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" index a451668..25348d0 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25415\351\241\271\357\274\232\344\275\277\347\261\273\345\222\214\346\210\220\345\221\230\347\232\204\345\217\257\350\256\277\351\227\256\346\200\247\346\234\200\345\260\217\345\214\226.md" @@ -2,7 +2,7 @@   要区分精心设计的组件和设计不好的组件的最重要的因素在于,这个组件对于其他组件而言,是否隐藏了其内部数据和其他市县细节。设计良好的组件会隐藏其所有实现细节,把它的 API 与它的实现完全分离。组件之间只能通过它们的 API 进行通信,并且不知道彼此之间内部的工作细节。这种被称为信息隐藏(information hiding )或封装(encapsulation)的概念是软件设计的基本原则[Parnas72]。 -  信息隐藏之所以非常重要是有许多原因的,其中大部分原因在于它将构成系统的组件解耦,允许它们单独开发、测试、优化、使用、理解和修改。这样可以加快系统开发的速度,因为这些组件可以并行开发。它也减轻了维护的负担,因为程序猿可以更快地理解、调试或者更换组件,而不用担心会影响其他组件。虽然信息隐藏本身无论是对内还是对外,都不会带来更好的性能,但是它可以实现有效的性能调优:一旦系统完成,并通过分析确定了哪些组件影响了系统的性能(第 67 项),那些组件可以在不影响正确性的情况下对其他模块进行优化。信息隐藏提高了软件的可重用性,因为组件之间的耦合度低,除了开发这些组件所使用的环境之外,他们在其他的环境中往往也很有用。最后,信息隐藏也降低了构建大型系统的风险,因为即使整个系统不可用,这些独立的组件有可能是可用的。 +  信息隐藏之所以非常重要是有许多原因的,其中大部分原因在于它将构成系统的组件解耦,允许它们单独开发、测试、优化、使用、理解和修改。这样可以加快系统开发的速度,因为这些组件可以并行开发。它也减轻了维护的负担,因为程序员可以更快地理解、调试或者更换组件,而不用担心会影响其他组件。虽然信息隐藏本身无论是对内还是对外,都不会带来更好的性能,但是它可以实现有效的性能调优:一旦系统完成,并通过分析确定了哪些组件影响了系统的性能(第 67 项),那些组件可以在不影响正确性的情况下对其他模块进行优化。信息隐藏提高了软件的可重用性,因为组件之间的耦合度低,除了开发这些组件所使用的环境之外,他们在其他的环境中往往也很有用。最后,信息隐藏也降低了构建大型系统的风险,因为即使整个系统不可用,这些独立的组件有可能是可用的。   Java 有许多机制(facilities)来协助信息隐藏。访问控制机制(access control)机制[JLS, 6.6]制定了类、接口和成员的可访问性。实体的可访问性由其声明的位置确定,以及声明中出现的访问修饰符(private、protected 和 public)共同决定的。正确地使用这些修饰符对于信息隐藏至关重要。 @@ -59,7 +59,7 @@ public static final Thing[] values() {   要在这两种方法之间做出选择,得考虑客户端可能怎么处理这个结果。哪种返回类型会更加方便?哪种会得到更好的性能? -  在 Java 9 中,作为模块系统的一部分引入了两个额外的隐式访问级别。模块是一组包,就像包是一组类。模块可以通过其模块声明中的导出声明显式地导出它的一些包(按惯例包含在名为 module-info.java 的源文件中)。 模块外部无法访问模块中未公开包的公共成员和受保护成员;在模块中,可访问性不受导出声明的影响。 使用模块系统,您可以在模块中的包之间共享类,而不会让整个世界都可以看见它们(Using the module system allows you to share classes among packages within a module without making them visible to the entire world)。未导出包中的公共类的 public 和 protect 成员产生两个隐式访问级别,这是正常公共级别和受保护级别的模块内类似物( which are intramodular analogues of the normal public and protected levels)。这种共享需求相对较少,通常可以通过重新安排(rearranging)包里面的类来消除。有限实用的模块不仅为典型的 Java 程序猿提供访问保护,而且其性质主要是提供咨询【功能】(Not only is the access protection afforded by modules of limited utility to the typical Java programmer, and largely advisory in nature)。为了利用它,你必须将软件包分组到模块中,在模块声明中明确其所有依赖项,重新编排你的源代码树(source tree),并采取特殊操作以适应模块内对非模块化软件包的任何访问[Reinhold, 3]。现在说模块是否会在 JDK 本身之外得到广泛使用还为时过早。与此同时,除非你有迫切需要,否则最好避免使用它们。 +  在 Java 9 中,作为模块系统的一部分引入了两个额外的隐式访问级别。模块是一组包,就像包是一组类。模块可以通过其模块声明中的导出声明显式地导出它的一些包(按惯例包含在名为 module-info.java 的源文件中)。 模块外部无法访问模块中未公开包的公共成员和受保护成员;在模块中,可访问性不受导出声明的影响。 使用模块系统,您可以在模块中的包之间共享类,而不会让整个世界都可以看见它们(Using the module system allows you to share classes among packages within a module without making them visible to the entire world)。未导出包中的公共类的 public 和 protect 成员产生两个隐式访问级别,这是正常公共级别和受保护级别的模块内类似物( which are intramodular analogues of the normal public and protected levels)。这种共享需求相对较少,通常可以通过重新安排(rearranging)包里面的类来消除。有限实用的模块不仅为典型的 Java 程序员提供访问保护,而且其性质主要是提供咨询【功能】(Not only is the access protection afforded by modules of limited utility to the typical Java programmer, and largely advisory in nature)。为了利用它,你必须将软件包分组到模块中,在模块声明中明确其所有依赖项,重新编排你的源代码树(source tree),并采取特殊操作以适应模块内对非模块化软件包的任何访问[Reinhold, 3]。现在说模块是否会在 JDK 本身之外得到广泛使用还为时过早。与此同时,除非你有迫切需要,否则最好避免使用它们。   总而言之,您应该尽可能地减少程序元素的可访问性(在合理范围内)。在仔细设计了最小的公共 API 之后,您应该防止任何杂散(stray)类、接口或成员成为 API 的一部分。除了作为常量的公共静态 final 字段之外,公共类应该没有公共字段。确保公共的静态 final 字段引用的对象是不可变的。 diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" index 717cd38..0685c22 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25416\351\241\271\357\274\232\345\234\250\345\205\254\346\234\211\347\261\273\344\270\255\344\275\277\347\224\250\350\256\277\351\227\256\346\226\271\346\263\225\350\200\214\351\235\236\345\205\254\346\234\211\345\237\237.md" @@ -10,7 +10,7 @@ class Point { } ``` -  由于这种类的数据域是可以被直接访问的,这些类没有提供封装(encapsulation)(第 15 项)。如果不改变 API,就无法改变他的数据表示法,也无法强加任何约束条件;当字段被访问的时候,无法采取任何辅助的行为。坚持面向对象程序设计的程序猿面对这种类深恶痛绝,认为应该用包含私有字段和公共访问方法(getters)的类代替。对于可变的类来说,应该用包含私有字段和公有设置方法(setters)的类代替: +  由于这种类的数据域是可以被直接访问的,这些类没有提供封装(encapsulation)(第 15 项)。如果不改变 API,就无法改变他的数据表示法,也无法强加任何约束条件;当字段被访问的时候,无法采取任何辅助的行为。坚持面向对象程序设计的程序员面对这种类深恶痛绝,认为应该用包含私有字段和公共访问方法(getters)的类代替。对于可变的类来说,应该用包含私有字段和公有设置方法(setters)的类代替: ```java // Encapsulation of data by accessor methods and mutators diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" index e66771c..1bc9b98 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25417\351\241\271\357\274\232\344\275\277\345\217\257\345\217\230\346\200\247\346\234\200\345\260\217\345\214\226.md" @@ -60,7 +60,7 @@ public final class Complex {   这个类表示一个复数(complex number)(一个具有实部和虚部的数)。除了标准的 Object 方法之外,它还提供了针对实部和虚部的访问方法,以及四种基本的算术运算:加法、减法、乘法和除法。注意这些算术运算是如何创建并返回新的 Complex 实例,而不是修改这个实例。这种模式成为函数方法(functional approach),因为方法返回的是将函数应用于其操作数的结果,而不是修改它。将其与过程式(procedural)或命令式(imperative)方法进行对比,它们的方法是将过程应用于其操作数,从而导致其状态发生变化。请注意,方法名称是介词(例如 plus)而不是动词(例如 add)。这强调了方法不会改变对象值的事实。BigInteger 和 BigDecimal 类不遵守此命名约定,并导致许多错误。 -  如果你对函数方式的做法【函数式编程】还不太熟悉,可能会觉得它显得太不自然,但是它带来了不可变性,具有许多优点。 **不可变对象比较简单** 不可变对象可以只有一种状态,即被创建时的状态。如果你能够确保所有的构造器都建立了这个类的约束关系(invariants),就可以确保这些约束关系在整个生命周期内永远不再发生变化,你和使用这个类的程序猿就不需要再做额外的工作【来维护这些约束关系】。另一方面,可变对象可以具有任意复杂的状态空间。如果文档中没有对 mutator 方法所执行的状态装换提供精确的描述,则要可靠地使用一个可变类是非常困难的,甚至是不可能的。 +  如果你对函数方式的做法【函数式编程】还不太熟悉,可能会觉得它显得太不自然,但是它带来了不可变性,具有许多优点。 **不可变对象比较简单** 不可变对象可以只有一种状态,即被创建时的状态。如果你能够确保所有的构造器都建立了这个类的约束关系(invariants),就可以确保这些约束关系在整个生命周期内永远不再发生变化,你和使用这个类的程序员就不需要再做额外的工作【来维护这些约束关系】。另一方面,可变对象可以具有任意复杂的状态空间。如果文档中没有对 mutator 方法所执行的状态装换提供精确的描述,则要可靠地使用一个可变类是非常困难的,甚至是不可能的。   **不可变对象本质上是线程安全的,它们不要求同步。** 他们不会因为被多个线程同时访问而受到损坏。这是实现线程安全的最简单的方法。因为没有任何线程会注意到其他线程对于不可变对象的影响,因此,**不可变对象可以被自由地共享。** 不可变类应该充分利用这种优势,顾里客户端尽可能地重用现有的实例。要做到这点,一个很简便的方法就是,对于频繁用到的值,为它们提供公有的静态 final 常量。例如,Complex 类有可能提供以下常量: diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" index 6edb5ad..a9c6a22 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25418\351\241\271\357\274\232\345\244\215\345\220\210\344\274\230\345\205\210\344\272\216\347\273\247\346\211\277.md" @@ -1,6 +1,6 @@ ## 复合优先于继承 -  继承(inheritance)是实现代码重用的有力手段,但它并非永远是完成这项工作的最佳工具。使用不当会导致软件变得很脆弱。在包的内部使用继承是非常安全的,在那里,子类和超类的实现都处在同一个程序猿的控制之下。对于专门为了继承而设计、并且具有很好的文档说明的类来说(第 19 项),使用继承也是非常安全的。然而,跨越包边界,从普通的具体类(concrete class)继承,则是非常危险的(Inheriting from ordinary concrete classes across package boundaries,however, is dangerous)。提示一下,本书使用“继承”一词,含义是实现继承(implementation inheritance)(当一个类扩展另一个类的时候)。本项中讨论的问题并不适用于接口继承(interface inheritance)(当一个类实现一个接口的时候,或者当一个接口扩展另一个接口的时候)。 +  继承(inheritance)是实现代码重用的有力手段,但它并非永远是完成这项工作的最佳工具。使用不当会导致软件变得很脆弱。在包的内部使用继承是非常安全的,在那里,子类和超类的实现都处在同一个程序员的控制之下。对于专门为了继承而设计、并且具有很好的文档说明的类来说(第 19 项),使用继承也是非常安全的。然而,跨越包边界,从普通的具体类(concrete class)继承,则是非常危险的(Inheriting from ordinary concrete classes across package boundaries,however, is dangerous)。提示一下,本书使用“继承”一词,含义是实现继承(implementation inheritance)(当一个类扩展另一个类的时候)。本项中讨论的问题并不适用于接口继承(interface inheritance)(当一个类实现一个接口的时候,或者当一个接口扩展另一个接口的时候)。   **与方法调用不用的是,继承打破了封装性[Snyder86]。** 换句话说,子类依赖于其超类中特定功能的实现。超类的实现有可能会随着版本的不同而有所变化,如果真的发生了变化,子类可能会遭受到破坏,即使它的代码完全没有改变。因而,子类必须跟着其超类的更新而演变,除非超类是专门为了扩展而设计的,并且具有很好的文档说明。 diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" index c113f7b..3db6308 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25419\351\241\271\357\274\232\350\246\201\344\271\210\344\270\272\347\273\247\346\211\277\350\200\214\350\256\276\350\256\241\357\274\214\345\271\266\346\217\220\344\276\233\346\226\207\346\241\243\357\274\214\350\246\201\344\271\210\345\260\261\347\246\201\346\255\242\347\273\247\346\211\277.md" @@ -17,13 +17,13 @@ public boolean remove(Object o)   实现要求:该实现遍历整个集合来查找指定的元素。如果它找到该元素,将会利用迭代器的 remove 方法将之从集合中删除。注意,如果由该集合的 iterator 方法返回的迭代器没有实现 remove 方法并且该集合包含这个特殊的对象,该实现就会抛出 UnsupportedOperationException。) -  该文档清楚地说明了,覆盖 iterator 方法将会影响 remove 方法的行为。而且,它确切地描述了 iterator 方法返回的 Iterator 的行为将会怎样影响 remove 方法的行为。与此相反的是,在第 18 项的情形中,程序猿在子类化 HashSet 的时候,并无法说明覆盖 add 方法是否会影响 addAll 方法的行为。 +  该文档清楚地说明了,覆盖 iterator 方法将会影响 remove 方法的行为。而且,它确切地描述了 iterator 方法返回的 Iterator 的行为将会怎样影响 remove 方法的行为。与此相反的是,在第 18 项的情形中,程序员在子类化 HashSet 的时候,并无法说明覆盖 add 方法是否会影响 addAll 方法的行为。   关于程序文档有句格言:好的 API 文档应该描述一个给定的方法做了什么工作,而不是描述它是如何做到的。那么,上面这种做法是否违背了这句格言呢?是的,它确实违背了!这正是继承破坏了封装性所带来的不幸后果。所以,为了设计一个类的文档,以便它能够被安全地子类化,你必须描述清楚那些有可能未指定的实现细节。   @implSpec 标签是在 Java 8 中添加的,而且在 Java 9 中用的很频繁。这个标签应该默认开启,但是在 Java 9 中,除非你传递命令行开关-tag "apoNote:a:API Note:",否则 javadoc 实用程序仍然会忽略它。 -  为了继承而进行设计不仅仅涉及自用模式的文档设计。为了使程序猿能够编写出更加有效的子类,而无需承受不必要的痛苦,**一个类必须通过某种形式提供适当的钩子(hook),以便能够进入它的内部工作流中,这种形式可以是精心选择的受保护的(protected)方法,** 也可以是受保护的字段,后者比较少见。例如,考虑 java.util.AbstractList 中的 removeRange 方法: +  为了继承而进行设计不仅仅涉及自用模式的文档设计。为了使程序员能够编写出更加有效的子类,而无需承受不必要的痛苦,**一个类必须通过某种形式提供适当的钩子(hook),以便能够进入它的内部工作流中,这种形式可以是精心选择的受保护的(protected)方法,** 也可以是受保护的字段,后者比较少见。例如,考虑 java.util.AbstractList 中的 removeRange 方法: ```java protected void removeRange(int fromIndex, int toIndex) @@ -56,7 +56,7 @@ Parameters:   在为了继承而设计有可能被广泛使用的类时,必须要意识到,对于文档中所说明的自用模式(self-use pattern),以及对于其受保护的方法和字段中所隐含的实现策略,你实际上已经做出了永久的承诺。这些承诺使得你在后续的版本中提高这个类的性能或者增加新功能都变得非常困难,甚至不可能。因此,**你必须在发布类之前先编写子类对类进行测试。** -  还要注意,因继承而需要的特殊文档会打乱正常的文档信息,普通的文档被设计用来让程序猿可以创建该类的实例,并调用该类中给的方法。在编写本书之时,几乎还没有适当的工具或者注释规范,能够把“普通的 API 文档”与“专门针对实现子类的程序猿你的信息”分开来。 +  还要注意,因继承而需要的特殊文档会打乱正常的文档信息,普通的文档被设计用来让程序员可以创建该类的实例,并调用该类中给的方法。在编写本书之时,几乎还没有适当的工具或者注释规范,能够把“普通的 API 文档”与“专门针对实现子类的程序员你的信息”分开来。   为了允许继承,类还必须遵守其他一些约束。**构造器决不能调用可被覆盖的方法,** 无论是直接调用还是间接调用。如果违反了这条规则,很有可能导致程序失败。超类的构造器在子类的构造器之前运行,所以子类中覆盖版本的方法将会在子类的构造器运行之前就先被调用。如果该覆盖版本的方法依赖于子类构造器所执行的任何初始化工作,该方法将不会如预期般地执行。为了更加直观地说明这一点,下面举个例子,其中有个类违反了这条规则: @@ -98,7 +98,7 @@ public final class Sub extends Super {   注意,在构造器中调用私有方法、final 方法和静态方法是安全的,因为这三种方法没有一种是可以被覆盖的。 -  在为了继承而设计类的时候,Cloneable 和 Serializable 接口出现了特殊的困难。如果类是为了继承而被设计的,无论实现这其中的哪个接口通常都不是个好的主意,因为它们给扩展类的程序员带来了沉重的负担。然而,你还是可以采取一些特殊的手段,使得子类实现这些接口,无需强迫子类的程序猿去承担这些负担。第 13 项和第 86 项就讲述了这些特殊的手段。 +  在为了继承而设计类的时候,Cloneable 和 Serializable 接口出现了特殊的困难。如果类是为了继承而被设计的,无论实现这其中的哪个接口通常都不是个好的主意,因为它们给扩展类的程序员带来了沉重的负担。然而,你还是可以采取一些特殊的手段,使得子类实现这些接口,无需强迫子类的程序员去承担这些负担。第 13 项和第 86 项就讲述了这些特殊的手段。   如果你决定在一个为了继承而设计的类中实现 Cloneable 或者 Serializable 接口,就应该意识到,因为 clone 和 readObject 方法在行为上非常类似于构造器,所以类似的限制规则也是适用的:**无论是 clone 还是 readObject,都不可以调用可覆盖的方法,不管是以直接还是间接的方式。** 对于 readObject 方法,覆盖版本的方法将在子类的状态被反序列化(deserialized)之前先被运行。而对于 clone 方法,覆盖版本的方法则是在子类的 clone 方法有机会修正被克隆对象的状态之前先被运行。无论是哪种情形,都不可避免地将导致程序失败。在 clone 方法的情形中,这种失败可能会同时损害到原始的对象以及被克隆的对象本身。例如,如果覆盖版本的方法假设它正在修改对象深层结构的克隆对象的备份,就会发生这种情况,但是该备份还没有完成。 @@ -110,9 +110,9 @@ public final class Sub extends Super {   **这个问题的最佳解决方案是,对于那些并非为了安全地进行子类化而设计和编写文档的类,要禁止子类化。** 这里有两种办法可以禁止子类化。比较容易的办法是把这个类声明为 final 的。另一种办法是把所有的构造器都编程私有的,或者包级私有的,并增加一些公有的静态工厂来替代构造器。后一种办法在第 17 项中讨论过,它为内部使用子类提供了灵活性。这两种办法都是可以接受的。 -  这条建议可能会引来争议,因为许多程序猿已经习惯于对普通的具体类进行子类化,以便增加新的功能设施,比如仪表功能(instrumentation,如计数显示等)、通知机制或者同步功能,或者为了限制原有类中的功能。如果实现了某个能够反映其本质的接口,比如 Set、List 或者 Map,就不应该为了禁止子类化而感到后悔。第 18 项中介绍的包装类(wrapper class)模式提供了另一种更好的办法,让继承机制实现更多的功能。 +  这条建议可能会引来争议,因为许多程序员已经习惯于对普通的具体类进行子类化,以便增加新的功能设施,比如仪表功能(instrumentation,如计数显示等)、通知机制或者同步功能,或者为了限制原有类中的功能。如果实现了某个能够反映其本质的接口,比如 Set、List 或者 Map,就不应该为了禁止子类化而感到后悔。第 18 项中介绍的包装类(wrapper class)模式提供了另一种更好的办法,让继承机制实现更多的功能。 -  如果具体的类没有实现标准的接口,那么禁止继承可能会给有些程序猿带来不便。如果你认为必须允许从这样的类继承,一种合理的办法是确保这个类永远不会调用它的任何可覆盖的方法,并在文档中说明这一点。换句话说,完全消除这个类中可覆盖方法的自用特性。这样做之后,就可以创建“能够安全地进行子类化”的类。覆盖方法将永远也不会影响其他任何方法的行为。 +  如果具体的类没有实现标准的接口,那么禁止继承可能会给有些程序员带来不便。如果你认为必须允许从这样的类继承,一种合理的办法是确保这个类永远不会调用它的任何可覆盖的方法,并在文档中说明这一点。换句话说,完全消除这个类中可覆盖方法的自用特性。这样做之后,就可以创建“能够安全地进行子类化”的类。覆盖方法将永远也不会影响其他任何方法的行为。   你可以机械地消除类中可覆盖方法的自用特性,而不改变它的行为。将每个可覆盖方法的代码体移到一个私有的“辅助方法(helper method)”中,并且让每个可覆盖的方法调用它的私有辅助方法。然后,用“直接调用可覆盖方法的私有辅助方法”来替代“可覆盖方法的每个自用调用”。 diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" index 3ce6b4f..27ff84b 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25420\351\241\271\357\274\232\346\216\245\345\217\243\344\274\230\345\205\210\344\272\216\346\212\275\350\261\241\347\261\273.md" @@ -29,15 +29,15 @@ public interface SingerSongwriter extends Singer, Songwriter {   你并不总是需要这中灵活性,但是一旦你这样做了,接口可就成了救世主。另一种做法是编写一个臃肿(bloated)的类层次,对于每一种要被支持的属性组合,都包含一个单独的类。如果在整个类型系统中有 n 个属性,那么就必须支持 2^n 种可能的组合。这种现象被称为“组合爆炸(combinatorial explosion)”。类层次臃肿会导致类也臃肿,这些类包含许多方法,并且这些方法只是在参数的类型上有所不同而已,因为类层次中没有任何类型体现了公共的行为特征。 -  通过第 18 项中介绍的包装类(wrapper class)模式,接口使得安全地增强类的功能称为可能。如果使用抽象类来定义类型,那么程序猿除了使用继承的手段来增加功能,没有其他的选择。这样得到的类与包装类相比,功能更差,也更加脆弱。 +  通过第 18 项中介绍的包装类(wrapper class)模式,接口使得安全地增强类的功能称为可能。如果使用抽象类来定义类型,那么程序员除了使用继承的手段来增加功能,没有其他的选择。这样得到的类与包装类相比,功能更差,也更加脆弱。 -  当根据其他接口方法显示实现接口方法时,请考虑以默认方法的形式向程序猿提供实现帮助。例如使用这种方式的一个例子,看【原书】第 104 页的`removeIf`方法。如果你提供了默认的方法,请务必使用 Javadoc 的标记@implSpec 来为它们的继承提供文档。 +  当根据其他接口方法显示实现接口方法时,请考虑以默认方法的形式向程序员提供实现帮助。例如使用这种方式的一个例子,看【原书】第 104 页的`removeIf`方法。如果你提供了默认的方法,请务必使用 Javadoc 的标记@implSpec 来为它们的继承提供文档。   使用默认方法提供的帮助是有限的。尽管许多接口都指定了 Object 方法(如 equals 和 hashCode)的行为,但是不允许为它们提供默认方法。此外,不允许接口包含实例字段或非公共静态成员(私有静态方法除外)。最后,你无法将默认方法添加到您无法控制的接口。   但是,你可以通过提供与接口一起使用的抽象骨架实现(skeletal implementation)类来结合接口和抽象类的优点。接口定义类型,可能提供一些默认方法,而骨架实现类在基本接口方法上实现剩余的非基本接口方法。扩展骨架实现需要完成大部分工作来实现接口。这是模板方法模式[Gamma95]。 -  按照惯例,骨架实现被称为 AbstractInterface,这里的 Interface 是指所实现的接口的名字。例如,Collections Framework 为每个重要的集合接口都提供了一个骨架实现,包括 AbstraceCollection、AbstractSet、AbstractList 和 AbstractMap。将它们称作 SkeletalCollection、SkeletalSet、SkeletalList 和 SkeletalMap 也是有道理的,但是现在 Abstract 的用法已经根深蒂固。如果设计得当,骨架实现(无论是否是单独的抽象类,或者仅包含接口上的默认方法)可以使程序猿很容易提供他们自己的接口实现。例如,这是一个静态工厂方法,基于 AbstractList 的包含一个完整的,功能齐全的 List 实现: +  按照惯例,骨架实现被称为 AbstractInterface,这里的 Interface 是指所实现的接口的名字。例如,Collections Framework 为每个重要的集合接口都提供了一个骨架实现,包括 AbstraceCollection、AbstractSet、AbstractList 和 AbstractMap。将它们称作 SkeletalCollection、SkeletalSet、SkeletalList 和 SkeletalMap 也是有道理的,但是现在 Abstract 的用法已经根深蒂固。如果设计得当,骨架实现(无论是否是单独的抽象类,或者仅包含接口上的默认方法)可以使程序员很容易提供他们自己的接口实现。例如,这是一个静态工厂方法,基于 AbstractList 的包含一个完整的,功能齐全的 List 实现: ```java // Concrete implementation built atop skeletal implementation diff --git "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" index b82e98f..5b822da 100644 --- "a/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" +++ "b/\347\254\25404\347\253\240\357\274\232\347\261\273\345\222\214\346\216\245\345\217\243/\347\254\25423\351\241\271\357\274\232\347\261\273\345\261\202\346\254\241\344\274\230\344\272\216\346\240\207\347\255\276\347\261\273.md" @@ -72,7 +72,7 @@ class Rectangle extends Figure { } ``` -  这个类层次纠正了前面提到过的标签类的所有缺点。这段代码简单且清楚,没有包含在原来的版本中所见到的所有样板代码。每个类型的实现都配有自己的类,这些类都没有受到不相关的数据字段的拖累。所有的字段都是 final 的。编译器确保每个类的构造器都初始化它的数据字段,对于根类中声明的每个抽象方法,都确保有一个实现。这样就杜绝了由于遗漏 switch case 而导致运行时失败的可能性。多个程序猿可以独立地扩展层次结构,并且不用访问根类的源代码就能相互操作。每种类型都有一种相关的独立的数据类型,允许程序猿指明变量的类型,限制变量,并将参数输入到特殊的类型。 +  这个类层次纠正了前面提到过的标签类的所有缺点。这段代码简单且清楚,没有包含在原来的版本中所见到的所有样板代码。每个类型的实现都配有自己的类,这些类都没有受到不相关的数据字段的拖累。所有的字段都是 final 的。编译器确保每个类的构造器都初始化它的数据字段,对于根类中声明的每个抽象方法,都确保有一个实现。这样就杜绝了由于遗漏 switch case 而导致运行时失败的可能性。多个程序员可以独立地扩展层次结构,并且不用访问根类的源代码就能相互操作。每种类型都有一种相关的独立的数据类型,允许程序员指明变量的类型,限制变量,并将参数输入到特殊的类型。   类层次结构的另一个优点是,他们可以同来反映类型之间的本质上的层次关系,从而提高灵活性和更好的编译时类型检查。假设原始示例中的标记类也允许使用正方形。可以使类层次结构反映正方形是一种特殊的矩形(假设两者都是不可变的)这一事实: diff --git "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" index 5117753..9a39539 100644 --- "a/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" +++ "b/\347\254\25405\347\253\240\357\274\232\346\263\233\345\236\213/\347\254\25429\351\241\271\357\274\232\344\274\230\345\205\210\350\200\203\350\231\221\346\263\233\345\236\213.md" @@ -135,7 +135,7 @@ public E pop() { } ``` -  消除通用数组创建的这两种技术都有它们的支持者。第一个更具有可读性:数组声明为 E[]类型,清楚地表明它只包含 E 实例。它也更简洁:在典型的泛型类中,你可以在代码中的很多地方读取数组;第一种技术只需要一次转换(创建数组的位置),而第二种技术每次读取数组元素时都需要单独的转换。因此,优选第一种,并且在实践中更常用第一种。但是,它会导致堆污染(heap pollution)(第 32 项):数组的运行时类型与其编译时的类型不匹配(除非 E 恰好是 Object)。这使得一些程序猿非常不安,他们选择第二种技术,尽管在这种情况下堆污染是无害的。 +  消除通用数组创建的这两种技术都有它们的支持者。第一个更具有可读性:数组声明为 E[]类型,清楚地表明它只包含 E 实例。它也更简洁:在典型的泛型类中,你可以在代码中的很多地方读取数组;第一种技术只需要一次转换(创建数组的位置),而第二种技术每次读取数组元素时都需要单独的转换。因此,优选第一种,并且在实践中更常用第一种。但是,它会导致堆污染(heap pollution)(第 32 项):数组的运行时类型与其编译时的类型不匹配(除非 E 恰好是 Object)。这使得一些程序员非常不安,他们选择第二种技术,尽管在这种情况下堆污染是无害的。   下面的程序示范了泛型 Stack 类的使用。程序以相反的顺序打印出它的命令行参数,并转换成大写字母。如果要在从堆栈中弹出的元素上调用 String 的`toUpperCase`方法,并不需要显式的转换,并且会确保自动生成的转换会成功: diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" index 8cc4119..be3aa5a 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25434\351\241\271\357\274\232\347\224\250enum\344\273\243\346\233\277int\345\270\270\351\207\217.md" @@ -111,7 +111,7 @@ Weight on NEPTUNE is 210.208751   与枚举常量关联的有些行为,可能只需要在定义了枚举的类或者包中。这种行为最好被实现成私有的或者包级私有的方法。然后,每个枚举常量都带有一组隐蔽的行为,这使得包含该枚举的类或者包在遇到这种常量时都可以做出适当的反应。就像其他的类一样,除非迫不得已要将枚举方法导出至它的客户端,否则都应该将它声明为私有的,如有必要,则声明为包级私有的(第 15 项)。 -  如果一个枚举具有普遍的适用性,它就应该成为一个顶级类(top-level class);如果它只是被用在一个特定的顶级类中,他就应该成为该顶级类的一个成员类(第 24 项)。例如,java.math.RoundingMode 枚举表示十进制小数的舍入模式(rounding mode)。这些舍入模式用于 BigDecimal 类,但是它们提供了一个非常有用的抽象,这种抽象本质上又不属于 BigDecimal 类。通过使用 RoundingMode 变成一个顶级类,库的设计者鼓励任何需要舍入模式的程序猿重用这个枚举,从而增强 API 之间的一致性。 +  如果一个枚举具有普遍的适用性,它就应该成为一个顶级类(top-level class);如果它只是被用在一个特定的顶级类中,他就应该成为该顶级类的一个成员类(第 24 项)。例如,java.math.RoundingMode 枚举表示十进制小数的舍入模式(rounding mode)。这些舍入模式用于 BigDecimal 类,但是它们提供了一个非常有用的抽象,这种抽象本质上又不属于 BigDecimal 类。通过使用 RoundingMode 变成一个顶级类,库的设计者鼓励任何需要舍入模式的程序员重用这个枚举,从而增强 API 之间的一致性。   Planet 示例中所示的方法对于大多数枚举类型来说就足够了,但你有时候会需要更多的方法。每个 Planet 常量都关联了不同的数据,但你有时候需要将本质上不同的行为(behavior)与每个常量关联起来。例如,假设你在编写一个枚举类型,来表示计算器的四大基本操作(即加减乘除),你想要提供一个方法来执行每个常量所表示的算术运算。有一种方法是通过启用枚举的值来实现: diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" index 59ad1ed..d3cdc86 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25435\351\241\271\357\274\232\347\224\250\345\256\236\344\276\213\345\237\237\344\273\243\346\233\277\345\272\217\346\225\260.md" @@ -28,7 +28,7 @@ public enum Ensemble { } ``` -  Enum 规范中谈到 ordinal 时是这么写的:“大多数程序猿都不需要这个方法。它这么设计的目的是用于像 EnumSet 和 EnumMap 这种基于枚举的通用数据结构的。”除非你在编写的是这种数据结构,否则最好避免使用 ordinal 方法。 +  Enum 规范中谈到 ordinal 时是这么写的:“大多数程序员都不需要这个方法。它这么设计的目的是用于像 EnumSet 和 EnumMap 这种基于枚举的通用数据结构的。”除非你在编写的是这种数据结构,否则最好避免使用 ordinal 方法。 > - [第 34 项:用 enum 代替 int 常量](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第34项:用enum代替int常量.md) > - [第 36 项:用 EnumSet 代替位域](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" index 2146dbe..1530a9c 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25436\351\241\271\357\274\232\347\224\250EnumSet\344\273\243\346\233\277\344\275\215\345\237\237.md" @@ -22,7 +22,7 @@ public class Text {   位域表示法也允许利用位操作,有效地执行像 nuion(并集)和 intersection(交集)这样的集合操作。但位域有着 int 枚举常量的所有缺点,甚至更多。当位域以数字形式打印时,翻译位域比翻译简单的 int 枚举常量要困难得多。甚至,要遍历位域表示的所有元素也没有很容易的办法。最后,在你编写 API 的时候就需要预测需要的最大位数,并选择相应的位域(通常为 int 或 long)类型。一旦选择了类型,在不修改 API 的情况下就不能超过其宽度(32 或 64 位)。 -  有些程序猿优先使用枚举而非 int 常量,他们在需要传递多组常量集时,仍然倾向于使用位域,其实没理由这么做,因为还有更好的替代方法。java.util 包提供了 EnumSet 类来有效地表示从单个枚举类型中提取的多个值的多个集合。这个类实现 Set 接口,提供了丰富的功能、类型安全性,以及可以从任何其他 Set 实现中得到的互用性。但是在内部的具体实现上,每个 EnumSet 内容都表示为位矢量。如果底层枚举类型有 64 个或者更少的元素————大多如此————整个 EnumSet 就是用单个 long 来表示,因此它的性能比得上位域的性能。批处理,如 removeAll 和 retainAll,都是利用位算法来实现的,就像手动替位域实现的那样。但是可以避免手动操作位域时容易出现的错误以及不太雅观的代码,因为 EnumSet 替你完成了这项艰巨的工作。 +  有些程序员优先使用枚举而非 int 常量,他们在需要传递多组常量集时,仍然倾向于使用位域,其实没理由这么做,因为还有更好的替代方法。java.util 包提供了 EnumSet 类来有效地表示从单个枚举类型中提取的多个值的多个集合。这个类实现 Set 接口,提供了丰富的功能、类型安全性,以及可以从任何其他 Set 实现中得到的互用性。但是在内部的具体实现上,每个 EnumSet 内容都表示为位矢量。如果底层枚举类型有 64 个或者更少的元素————大多如此————整个 EnumSet 就是用单个 long 来表示,因此它的性能比得上位域的性能。批处理,如 removeAll 和 retainAll,都是利用位算法来实现的,就像手动替位域实现的那样。但是可以避免手动操作位域时容易出现的错误以及不太雅观的代码,因为 EnumSet 替你完成了这项艰巨的工作。   下面是前一个范例改成用枚举代替位域后的代码,它更加简短、更加清楚,也更加安全: diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" index 9950bae..d0af6f9 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25437\351\241\271\357\274\232\347\224\250EnumMap\344\273\243\346\233\277\345\272\217\346\225\260\347\264\242\345\274\225.md" @@ -18,7 +18,7 @@ class Plant { } ``` -  现在假设有一个 Plant 数组来表示一座花园的植物,你想要根据它们的生命周期(一年生、多年生或者两年生)进行组织之后将这些植物列出来。如果要这么做的话,需要构建三个集合,每种生命周期一个集合,并遍历整座花园,将每种植物放到相应的集合中。一些程序猿会通过将这些集合放到一个按照生命周期的序数进行索引的数组中来实现这一点。 +  现在假设有一个 Plant 数组来表示一座花园的植物,你想要根据它们的生命周期(一年生、多年生或者两年生)进行组织之后将这些植物列出来。如果要这么做的话,需要构建三个集合,每种生命周期一个集合,并遍历整座花园,将每种植物放到相应的集合中。一些程序员会通过将这些集合放到一个按照生命周期的序数进行索引的数组中来实现这一点。 ```java // Using ordinal() to index into an array - DON'T DO THIS! @@ -47,7 +47,7 @@ for (Plant p : garden) System.out.println(plantsByLifeCycle); ``` -  这段程序更简短、更清楚、也更加安全,运行速度方面可以与使用序数的程序相媲美。它没有不安全的转换;不必手动标注这些索引的输出,因为映射键知道如何将自身翻译成可打印字符串的枚举;计算数组索引时也不可能出错。EnumMap 在运行速度方面之所以能与通过序数索引的数组相媲美,是因为 EnumMap 在内部使用了这种数组。但是它对程序猿隐藏了这种实现细节集 Map 的丰富功能和那个使用索引安全访问的数组的快速于一身。注意 EnumMap 构造器采用键类型的 Class 对象:这是一个有限制的类型令牌(bounded type token),它提供了运行时的泛型信息(第 33 项)。 +  这段程序更简短、更清楚、也更加安全,运行速度方面可以与使用序数的程序相媲美。它没有不安全的转换;不必手动标注这些索引的输出,因为映射键知道如何将自身翻译成可打印字符串的枚举;计算数组索引时也不可能出错。EnumMap 在运行速度方面之所以能与通过序数索引的数组相媲美,是因为 EnumMap 在内部使用了这种数组。但是它对程序员隐藏了这种实现细节集 Map 的丰富功能和那个使用索引安全访问的数组的快速于一身。注意 EnumMap 构造器采用键类型的 Class 对象:这是一个有限制的类型令牌(bounded type token),它提供了运行时的泛型信息(第 33 项)。   通过使用流(stream)(第 45 项)来管理 map 可以使上面的程序更加简短。这是最简单的基于流的代码,它很大程度上复制了前一个示例的行为: @@ -168,7 +168,7 @@ public enum Phase {   为了简洁起见,上述示例使用 null 来表示不存在状态变化(其中往返是相同的)。这不是一个好习惯,很可能在运行时导致 NullPointerException 异常。为这个问题设计一个干净,优雅的解决方案是非常棘手的,并且生成的程序足够长,以至于它们会减损此项目中的主要成本。 -  总而言之,**最好不要用序数来索引数组,而要使用 EnumMap**。如果你所表示的这种关系是多维的,就使用 EnumMap<..., EnumMap<...>>。应用程序的程序猿在一般情况下都不适用 Enum.ordinal,即使要用也很少,因此这是一种特殊情况(第 35 项) +  总而言之,**最好不要用序数来索引数组,而要使用 EnumMap**。如果你所表示的这种关系是多维的,就使用 EnumMap<..., EnumMap<...>>。应用程序的程序员在一般情况下都不适用 Enum.ordinal,即使要用也很少,因此这是一种特殊情况(第 35 项) > - [第 36 项:用 EnumSet 代替位域](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第36项:用EnumSet代替位域.md) > - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" index f81c5e3..41a69b4 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25439\351\241\271\357\274\232\346\263\250\350\247\243\344\274\230\345\205\210\344\272\216\345\221\275\345\220\215\346\250\241\345\274\217.md" @@ -25,7 +25,7 @@ public @interface Test {   注意 Test 注解声明上方的注释:“Use only on parameterless static methods.(只用于无参的静态方法)。”如果编译器能够强制这一限制最好,但是它做不到。除非你写一个注释处理器这样做。有关此专题的更多信息,请参阅 javax.annotation.processing 的文档。在缺少这样的注释处理器的情况下,如果将 Test 注解放在实例方法的声明中,或者放在带有一个或者多个参数的方法中,测试程序仍然会编译,让测试工具在运行时来处理这个问题。 -  下面就是在实践中应用 Test 注解,称作*标记注解(marker annotation)*,因为它没有参数,只是“标注”被注解的元素。如果程序猿拼错了 Test,或者将 Test 注解应用到程序元素而非方法声明,程序就无法编译: +  下面就是在实践中应用 Test 注解,称作*标记注解(marker annotation)*,因为它没有参数,只是“标注”被注解的元素。如果程序员拼错了 Test,或者将 Test 注解应用到程序元素而非方法声明,程序就无法编译: ```java // Program containing marker annotations @@ -253,9 +253,9 @@ if (m.isAnnotationPresent(ExceptionTest.class) || m.isAnnotationPresent(Exceptio   添加了可重复的注释以提高源代码的可读性,逻辑上将相同注释类型的多个实例应用在给定的程序元素。如果你认为它们增强了源代码的可读性,请使用它们,但请记住,在声明和处理可重复的注释时有更多的样板,并且处理可重复的注释容易出错。 -  这个项目中的测试框架只是一个试验,但它清晰地证明了注释优于命名模式,它这只是揭开了注解功能的冰山一角。如果你是在编写一个需要程序猿给源文件添加信息的工具,请定义适当的注释类型。**当你可以使用注释时,根本没有理由使用命名模式**。 +  这个项目中的测试框架只是一个试验,但它清晰地证明了注释优于命名模式,它这只是揭开了注解功能的冰山一角。如果你是在编写一个需要程序员给源文件添加信息的工具,请定义适当的注释类型。**当你可以使用注释时,根本没有理由使用命名模式**。 -  也就是说,除了“工具铁匠(toolsmiths————特定的程序猿)”之外,大多数程序猿都不必定义注解类型。**但是所有的程序猿都应该使用 Java 平台所提供的预定义的注解类型(第 40、27 项)**。还要考虑使用 IDE 或者静态分析工具所提供的任何注解。这种注解可以提升由这些工具所提供的诊断信息的质量。但是要注意这些注解还没有标准化,因此如果变换工具或者形成标准,就有很多工作要做了。 +  也就是说,除了“工具铁匠(toolsmiths————特定的程序员)”之外,大多数程序员都不必定义注解类型。**但是所有的程序员都应该使用 Java 平台所提供的预定义的注解类型(第 40、27 项)**。还要考虑使用 IDE 或者静态分析工具所提供的任何注解。这种注解可以提升由这些工具所提供的诊断信息的质量。但是要注意这些注解还没有标准化,因此如果变换工具或者形成标准,就有很多工作要做了。 > - [第 38 项:用接口模拟可扩展的枚举](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第38项:用接口模拟可扩展的枚举.md) > - [第 40 项:坚持使用 Override 注解](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第06章:枚举和注解/第40项:坚持使用Overide注解.md) diff --git "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" index c7a7da9..899720a 100644 --- "a/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" +++ "b/\347\254\25406\347\253\240\357\274\232\346\236\232\344\270\276\345\222\214\346\263\250\350\247\243/\347\254\25440\351\241\271\357\274\232\345\235\232\346\214\201\344\275\277\347\224\250Overide\346\263\250\350\247\243.md" @@ -1,6 +1,6 @@ ## 坚持使用 Overide 注解 -  Java 库包含多种注释类型。对于传统的程序猿,其中最重要的就是@Override。该注解只能用于方法声明,它表示被注解的方法声明会覆盖超类中的声明。如果坚持使用这个注解,可以防止一大类的非法错误。考虑下面的程序,这里的类 Bigram 表示一个*双字母组*或者有序的字母对: +  Java 库包含多种注释类型。对于传统的程序员,其中最重要的就是@Override。该注解只能用于方法声明,它表示被注解的方法声明会覆盖超类中的声明。如果坚持使用这个注解,可以防止一大类的非法错误。考虑下面的程序,这里的类 Bigram 表示一个*双字母组*或者有序的字母对: ```java // Can you spot the bug? @@ -29,7 +29,7 @@ public class Bigram {   main 程序反复地将 26 个双字母组添加到集合中,每个双字母组都由两个相同的小写字母组成。然后它打印出集合的大小。你可能以为程序打印出的大小为 26,因为集合不能包含重复【元素】。如果你试着运行程序,会发现它打印的不是 26 而是 260。哪里出错了呢? -  很显然,Bigram 类的创建者原本想要覆盖 equals 方法(第 10 项),同时还记得覆盖了 hashCode。遗憾的是,不幸的程序猿没能覆盖 equals,而是将它重载了(第 52 项)。为了覆盖 Object.equals,必须定义一个参数为 Object 类型的 equals 方法,但是 Bigram 的 equals 方法的参数并不是 Object 类型,因此 Bigram 从 Object 继承了 equals 方法。这个 equals 方法测试对象的同一性,就像==操作符一样。每个 bigram 的 10 个备份中,每一个都与其余的 9 个不同,因此 Object.equals 认为它们不相等,这正解释了程序为什么会打印出 260 的原因。 +  很显然,Bigram 类的创建者原本想要覆盖 equals 方法(第 10 项),同时还记得覆盖了 hashCode。遗憾的是,不幸的程序员没能覆盖 equals,而是将它重载了(第 52 项)。为了覆盖 Object.equals,必须定义一个参数为 Object 类型的 equals 方法,但是 Bigram 的 equals 方法的参数并不是 Object 类型,因此 Bigram 从 Object 继承了 equals 方法。这个 equals 方法测试对象的同一性,就像==操作符一样。每个 bigram 的 10 个备份中,每一个都与其余的 9 个不同,因此 Object.equals 认为它们不相等,这正解释了程序为什么会打印出 260 的原因。   幸运的是,编译器可以帮助你发现这个错误,但是只有当你告知编译器你想要覆盖 Object.equals 时才行。为了做到这一点,要用@Override 标注 Bigram.equals,如下所示: diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" index 6f440ea..d3a9a03 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25445\351\241\271\357\274\232\350\260\250\346\205\216\344\275\277\347\224\250Stream.md" @@ -65,7 +65,7 @@ public class Anagrams { } ``` -  如果你发现此代码难以阅读,请不要担心; 你不是一个人。它更短,但可读性更小,特别是对于不是使用流的专家级程序猿。**过度使用流会使程序难以阅读和维护**。 +  如果你发现此代码难以阅读,请不要担心; 你不是一个人。它更短,但可读性更小,特别是对于不是使用流的专家级程序员。**过度使用流会使程序难以阅读和维护**。   幸运的是,有一个让人开心的工具。以下程序使用流而不会过度使用流来解决相同的问题。结果是一个比原始程序更短更清晰的程序: @@ -179,7 +179,7 @@ private static List newDeck() { } ``` -  newDeck 的两个版本中哪一个更好?它归结为个人偏好和你的编程环境。第一个版本更简单,也许感觉更自然。大部分 Java 程序猿将能够理解和维护它,但是一些程序猿会对第二个(基于流的)版本感觉更舒服。如果你对流和函数式编程很精通,那么它会更简洁,也不会太难理解。如果你不确定自己喜欢哪个版本,则迭代版本可能是更安全的选择。如果你更喜欢流版本,并且你相信其他使用该代码的程序猿跟你有共同的偏好,那么你应该使用它。 +  newDeck 的两个版本中哪一个更好?它归结为个人偏好和你的编程环境。第一个版本更简单,也许感觉更自然。大部分 Java 程序员将能够理解和维护它,但是一些程序员会对第二个(基于流的)版本感觉更舒服。如果你对流和函数式编程很精通,那么它会更简洁,也不会太难理解。如果你不确定自己喜欢哪个版本,则迭代版本可能是更安全的选择。如果你更喜欢流版本,并且你相信其他使用该代码的程序员跟你有共同的偏好,那么你应该使用它。   总之,一些任务最好用流完成,其他任务最好用遍历完成。通过组合这两种方法可以最好地完成许多任务。选择哪种方法用于任务没有硬性规定,但有一些有用的启发式方法。在许多情况下,将清楚使用哪种方法; 在某些情况下,它不会。**如果你不确定某个任务是否更适合流或遍历,那么就两个都尝试一下,并看一下哪个更好**。 diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" index d175a8c..8b01480 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25446\351\241\271\357\274\232\344\274\230\345\205\210\351\200\211\346\213\251Stream\344\270\255\346\227\240\345\211\257\344\275\234\347\224\250\347\232\204\345\207\275\346\225\260.md" @@ -31,7 +31,7 @@ try (Stream words = new Scanner(file).tokens()) {   改进的代码使用了一个*收集器(collector)*,这是一个新概念,你必须学习了才能使用流。Collectors API 是令人生畏的:它有三十九种方法,其中一些方法有多达五种类型参数。好消息是,你可以从这个 API 中获得大部分好处,而无需深入研究其完整的复杂性。对于初学者,你可以忽略 Collector 接口,并将收集器视为封装缩减策略的不透明对象(an opaque object that encapsulates a reduction strategy)。在这种情况下,缩减意味着将流的元素组合成单个对象。收集器生成的对象通常是一个集合(它代表名称收集器((which accounts for the name collector))。 -  用于将流的元素收集到真正的集合中的收集器是很简单的。有三个这样的收集器:toList(),toSet()和 toCollection(collectionFactory)。它们分别返回一个集合,一个列表和一个程序猿指定的集合类型。有了这些知识,我们可以编写一个流管道来从频率表中提取前十个列表。 +  用于将流的元素收集到真正的集合中的收集器是很简单的。有三个这样的收集器:toList(),toSet()和 toCollection(collectionFactory)。它们分别返回一个集合,一个列表和一个程序员指定的集合类型。有了这些知识,我们可以编写一个流管道来从频率表中提取前十个列表。 ```java // Pipeline to get a top-ten list of words from a frequency table @@ -94,7 +94,7 @@ Map freq = words.collect(groupingBy(String::toLowerCase, counting(   groupingBy 的第三个版本允许你指定除下游收集器之外的 map 工厂。请注意,此方法违反了标准的 telescoping 参数列表模式:mapFactory 参数位于 downStream 参数之前,而不是之后。此版本的 groupingBy 使你可以控制包含的映射以及包含的集合(This version of groupingBy gives you control over the containing map as well as the contained collections),因此,例如,你可以指定一个收集器,该收集器返回一个 value 为 TreeSet 的 TreeMap。 -  groupingByConcurrent 方法提供了 groupingBy 的所有三个重载的变体。 这些变体并行高效运行并生成 ConcurrentHashMap 实例。还有一个很少使用的 grouping 的相近【的方法】叫做 partitioningBy。代替分类器方法,它接收一个谓词(predicate)并返回键为布尔值的 map。此方法有两个重载【版本】,其中一个除谓词之外还包含下游收集器。通过 counting 方法返回的收集器仅用作下游收集器。通过 count 方法直接在 Stream 上提供相同的功能,因此**没有理由说 collect(counting())( there is never a reason to say collect(counting()))** 。此属性还有十五种收集器方法。它们包括九个方法,其名称以 summing,averaging 和 summarizing 开头(其功能在相应的基本类型流上可用)。它们还包括 reducing 方法的所有重载,以及 filter,mapping,flatMapping 和 collectingAndThen 方法。大多数程序猿可以安心地忽略大多数这种方法。从设计角度来看,这些收集器代表了尝试在收集器中部分复制流的功能,以便下游收集器可以充当“迷你流(ministreams)”。 +  groupingByConcurrent 方法提供了 groupingBy 的所有三个重载的变体。 这些变体并行高效运行并生成 ConcurrentHashMap 实例。还有一个很少使用的 grouping 的相近【的方法】叫做 partitioningBy。代替分类器方法,它接收一个谓词(predicate)并返回键为布尔值的 map。此方法有两个重载【版本】,其中一个除谓词之外还包含下游收集器。通过 counting 方法返回的收集器仅用作下游收集器。通过 count 方法直接在 Stream 上提供相同的功能,因此**没有理由说 collect(counting())( there is never a reason to say collect(counting()))** 。此属性还有十五种收集器方法。它们包括九个方法,其名称以 summing,averaging 和 summarizing 开头(其功能在相应的基本类型流上可用)。它们还包括 reducing 方法的所有重载,以及 filter,mapping,flatMapping 和 collectingAndThen 方法。大多数程序员可以安心地忽略大多数这种方法。从设计角度来看,这些收集器代表了尝试在收集器中部分复制流的功能,以便下游收集器可以充当“迷你流(ministreams)”。   我们还有三种 Collectors 方法尚未提及。虽然他们在 Collectors 里面,但他们不涉及集合。前两个是 minBy 和 maxBy,它们取比较器并返回由比较器确定的流中的最小或最大元素。它们是 Stream 接口中 min 和 max 方法的小扩展【简单的实现】,是 BinaryOperator 中类似命名方法返回的二元运算符的收集器类似物。回想一下,我们在最畅销专辑的例子中使用了 BinaryOperator.maxBy。 diff --git "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" index e50346d..704f905 100644 --- "a/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" +++ "b/\347\254\25407\347\253\240\357\274\232Lambda\345\222\214Stream/\347\254\25447\351\241\271\357\274\232Stream\350\246\201\344\274\230\345\205\210\347\224\250Collection\344\275\234\344\270\272\350\277\224\345\233\236\347\261\273\345\236\213.md" @@ -47,7 +47,7 @@ for (ProcessHandle p : iterableOf(ProcessHandle.allProcesses())) {   请注意,第 34 项中的 Anagrams 程序的流版本使用 Files.lines 方法读取字典,而迭代版本使用 scanner。Files.lines 方法优于 scanner,它可以在读取文件时悄悄地处理(silently swallows)任何异常。理想情况下,我们也会在迭代版本中使用 Files.lines。如果 API 仅提供对序列的流的访问并且他们希望使用 for-each 语句遍历序列,那么程序员将会做出这种折中的方法【在迭代的版本中使用 Files.lines】。 -  相反,想要使用流管道处理序列的程序猿理所当然会因为 API 仅提供 Iterable 而感到难过【傲娇】。再提一次 JDK 没有提供适配器,但编写一个是很容易的: +  相反,想要使用流管道处理序列的程序员理所当然会因为 API 仅提供 Iterable 而感到难过【傲娇】。再提一次 JDK 没有提供适配器,但编写一个是很容易的: ```java // Adapter from Iterable to Stream diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" index 9c5d48d..e95b5ee 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25450\351\241\271\357\274\232\345\277\205\350\246\201\346\227\266\350\277\233\350\241\214\344\277\235\346\212\244\346\200\247\346\213\267\350\264\235.md" @@ -2,7 +2,7 @@   让 Java 使用起来如此舒适的一个因素在于,它是一门*安全的语言(safe language)*。这意味着,在没有 native 方法的情况下,它对于缓冲区溢出、数组越界、非法指针以及其他的内存破坏错误都自动免疫,而这些错误却困扰着诸如 C 和 C++这样的不安全的语言。在一门安全语言中,无论系统的其他部分发生什么事情,这些类的约束都是有效的。对于那些“把所有的内存当作一个巨大的数组来看待”的语言来说,这是不可能的。 -  即使在安全的语言中,如果不采取一点措施,还是无法与其他的类隔离开来。**假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性地设计程序**。随着人们为了破坏系统的安全性而付出了更多的努力,这种做法越来越正确,但更常见的是,你的类不得不处理那些善意的程序猿意外导致的错误。不管怎么说,编写一些面对客户出现不良行为时仍能保持健壮性的类,这是非常值得投入时间去做的事情。 +  即使在安全的语言中,如果不采取一点措施,还是无法与其他的类隔离开来。**假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性地设计程序**。随着人们为了破坏系统的安全性而付出了更多的努力,这种做法越来越正确,但更常见的是,你的类不得不处理那些善意的程序员意外导致的错误。不管怎么说,编写一些面对客户出现不良行为时仍能保持健壮性的类,这是非常值得投入时间去做的事情。   没有对象的帮助时,虽然另一个类不可能修改对象的内部状态,但是对象很容易在无意识的情况下提供这种帮助。例如,考虑下面的类,它声称可以代表一段不可变的时间周期: @@ -83,7 +83,7 @@ public Date end() { } ``` -  使用了新的构造函数和访问方法之后,Period 真正是不可变的了。不管程序猿是多么恶意,或者多么不合格,都绝对不会违反周期的起始时间不能落后于结束时间这个约束条件(不采用诸如 native 方法和反射之类的语言手段)。确实如此,因为除了 Period 类自身之外,其他任何类都无法访问 Period 实例中的任何一个可变域,这些域被真正封装在对象的内部。 +  使用了新的构造函数和访问方法之后,Period 真正是不可变的了。不管程序员是多么恶意,或者多么不合格,都绝对不会违反周期的起始时间不能落后于结束时间这个约束条件(不采用诸如 native 方法和反射之类的语言手段)。确实如此,因为除了 Period 类自身之外,其他任何类都无法访问 Period 实例中的任何一个可变域,这些域被真正封装在对象的内部。   访问方法和构造器不同,它们在进行保护性拷贝的时候允许使用 clone 方法。之所以如此,是因为我们知道,Period 内部的 Date 对象的类是 java.util.Date,而不可能是其他某个潜在的不可信子类。也就是说,基于第 13 项中所阐述的原因,一般情况下,最好使用构造函数或者静态工厂。 diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" index 1a3f631..3219b9b 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25451\351\241\271\357\274\232\350\260\250\346\205\216\350\256\276\350\256\241\346\226\271\346\263\225\347\255\276\345\220\215.md" @@ -6,7 +6,7 @@   **不要过于追求提供遍历的方法**。每个方法都应该尽其所能。方法太多会使类难以学习、使用、文档化、测试和维护。对于接口而言,这无疑是正确的,方法太多会使接口实现者和接口使用者的工作变得复杂起来。对于类和接口所支持的每个动作,都提供一个功能齐全的方法。只有当一项操作被经常用到的时候,才考虑为它提供快捷方式(shorthand)。**如果不能确定,还是不要提供快捷方式为好**。 -  **避免过长的参数列表**。目标是四个参数,或者更少。大多数程序猿都无法记住更长的参数列表。如果你编写的许多方法都超过了这个限制,你的 API 就不太便于使用,除非用户不停地参考它的文档。现代的 IDE 会有所帮助,但最好还是使用简短的参数列表。**相同类型的长参数序列格外有害**。用户不仅无法记住参数的顺序,而且,当他们不小心弄错了参数顺序时,他们的程序仍然可以编译和运行,只不过这些程序不会按照作者的意图进行工作。 +  **避免过长的参数列表**。目标是四个参数,或者更少。大多数程序员都无法记住更长的参数列表。如果你编写的许多方法都超过了这个限制,你的 API 就不太便于使用,除非用户不停地参考它的文档。现代的 IDE 会有所帮助,但最好还是使用简短的参数列表。**相同类型的长参数序列格外有害**。用户不仅无法记住参数的顺序,而且,当他们不小心弄错了参数顺序时,他们的程序仍然可以编译和运行,只不过这些程序不会按照作者的意图进行工作。   有三种方法可以缩短过长的参数列表。第一种是把方法分解成多个方法,每个方法只需要这些参数的一个子集。如果不小心,这样做会导致方法过多。但是通过提示它们的正交性(orthogonality),还可以*减少(reduce)*方法的数目。例如,考虑 java.util.List 接口。它并没有提供“在子列表(sublist)中查找元素的第一个索引和最后一个索引”的方法,这两个方法都需要三个参数。相反,它提供了 subList 方法,这个方法带有两个参数,并返回子列表的一个视图(view)。这个方法可以与 indexOf 或者 lastIndexOf 方法结合起来,获得期望的功能,而这两个方法都分别只有一个参数。而且,subList 方法也可以与其他任何“针对 List 实例进行操作”的方法结合起来,在子列表上执行任意的计算。这样得到的 API 就有很高的“功能-重量”(power-to-weight)比。 diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" index 88d6851..a015eb3 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25452\351\241\271\357\274\232\346\205\216\347\224\250\351\207\215\350\275\275.md" @@ -61,15 +61,15 @@ public static String classify(Collection c) { } ``` -  因为覆盖机制是规范,而重载机制是例外,所以,覆盖机制满足了人们对于方法调用行为的期望。正如 CollectionClassifier 例子所示,重载机制很容易使这些期望落空。如果编写出来的代码的行为可能使程序猿感到困惑,他就是很糟糕的实践。对于 API 来说尤其如此。如果 API 的普通用户根本不知道“对于一组给定的参数,其中的哪个重载方法将会被调用”,那么,使用这样的 API 就很可能出错。这些错误要等到运行时发生了怪异的行为之后才会显现出来,许多程序猿无法诊断出这样的错误。因此,应该**避免乱用重载机制**。 +  因为覆盖机制是规范,而重载机制是例外,所以,覆盖机制满足了人们对于方法调用行为的期望。正如 CollectionClassifier 例子所示,重载机制很容易使这些期望落空。如果编写出来的代码的行为可能使程序员感到困惑,他就是很糟糕的实践。对于 API 来说尤其如此。如果 API 的普通用户根本不知道“对于一组给定的参数,其中的哪个重载方法将会被调用”,那么,使用这样的 API 就很可能出错。这些错误要等到运行时发生了怪异的行为之后才会显现出来,许多程序员无法诊断出这样的错误。因此,应该**避免乱用重载机制**。 -  到底怎样才算乱用重载机制呢?这个问题仍然存在争议。**安全而保守的策略是,永远不要导出两个具有相同参数数目的重载方法**。如果方法使用可变参数(varargs),保守的策略是根本不需要重载它,除了第 53 项中描述的情形之外。如果你遵守这些限制,程序猿永远也不会陷入到“对于任何一组实际的参数,哪个重载方法是适用的”这样的疑问中。这项限制并不麻烦,因为**你始终可以给方法起不同的名称,而不使用重载机制**。 +  到底怎样才算乱用重载机制呢?这个问题仍然存在争议。**安全而保守的策略是,永远不要导出两个具有相同参数数目的重载方法**。如果方法使用可变参数(varargs),保守的策略是根本不需要重载它,除了第 53 项中描述的情形之外。如果你遵守这些限制,程序员永远也不会陷入到“对于任何一组实际的参数,哪个重载方法是适用的”这样的疑问中。这项限制并不麻烦,因为**你始终可以给方法起不同的名称,而不使用重载机制**。   例如,考虑 ObjectOutputStream 这个类。对于每个基本类型,以及几种引用类型,它的 write 方法都有一种变形。这些变形方法都有不一样的名字,而不是重载 write 方法,比如 writeBoolean(boolean), writeInt(int)和 writeLong(long)。实际上,ObjectInputStream 类正是提供了这样的读方法。   对于构造器,你没有选择使用不同名称的机会:一个类的多个构造器总是重载的。在许多情况下,可以选择导出静态工厂,而不是构造器(第 1 项)。而且,对于构造器,还不用担心重载和覆盖的相互影响,因为构造器不可能被覆盖。或许你有可能导出多个具有相同参数数目的构造器,所以有必要了解一下如何安全地做到这一点。 -  如果对于“任何一组给定的实际参数将应用在哪个重载方法上”始终非常清楚,那么,导出多个具有相同参数数目的重载方法就不可能使程序猿感到困惑。如果对于每一对重载方法,至少有一个对应的参数在两个重载方法中具有“根本不同(radically different)”的类型,就属于这种情况。如果使用任何非空表达式都无法将两种类型相互转换,那么这两种类型就是完全不同的(Two types are radically different if it is clearly impossible to cast any non-null expression to both types)。在这种情况下,一组给定的实际参数应用于哪个重载方法上就完全由参数的运行时类型来决定,不可能受到其编译时类型的影响,所以主要的混淆根源就消除了。例如,ArrayList 有一个构造器带一个 int 参数,另一个构造器带一个 Collection 参数。难以想象在什么情况下,会不清楚要调用哪一个构造器。 +  如果对于“任何一组给定的实际参数将应用在哪个重载方法上”始终非常清楚,那么,导出多个具有相同参数数目的重载方法就不可能使程序员感到困惑。如果对于每一对重载方法,至少有一个对应的参数在两个重载方法中具有“根本不同(radically different)”的类型,就属于这种情况。如果使用任何非空表达式都无法将两种类型相互转换,那么这两种类型就是完全不同的(Two types are radically different if it is clearly impossible to cast any non-null expression to both types)。在这种情况下,一组给定的实际参数应用于哪个重载方法上就完全由参数的运行时类型来决定,不可能受到其编译时类型的影响,所以主要的混淆根源就消除了。例如,ArrayList 有一个构造器带一个 int 参数,另一个构造器带一个 Collection 参数。难以想象在什么情况下,会不清楚要调用哪一个构造器。   在 Java 1.5 发行版之前,所有的基本类型与所有的引用类型都有根本上的不同,但是当自动装箱出现之后,就不再如此了,它会导致真正的麻烦。请考虑下面这个程序: @@ -122,11 +122,11 @@ exec.submit(System.out::println);   数组类型和 Object 之外的类截然不同。数组类型和 Serializable 与 Cloneable 之外的接口也截然不同。如果两种类都不是对方的后代,这两个独特的类就是不相关的(unrelated)\[JLS, 5.5\]。例如,String 和 Throwable 就是不相关的。任何对象都不可能是两个不相关的类的实例,因此不相关的类也是截然不同的。 -  还有其他一些“类型对”的例子也是不能相互转换的\[JLS, 5.1.12\]。但是,一旦超出了上述这些简单的情形,大多数程序猿要想搞清楚“一组实际的参数应用于哪个重载方法上”就会非常困难。确定选择哪个重载方法的规则是非常复杂的,并且每个版本都会变得更加复杂。很少有程序猿能够理解其中的所有微妙之处。 +  还有其他一些“类型对”的例子也是不能相互转换的\[JLS, 5.1.12\]。但是,一旦超出了上述这些简单的情形,大多数程序员要想搞清楚“一组实际的参数应用于哪个重载方法上”就会非常困难。确定选择哪个重载方法的规则是非常复杂的,并且每个版本都会变得更加复杂。很少有程序员能够理解其中的所有微妙之处。   有时候,尤其是在更新现有类的时候,可能会被迫违反本项中的指导原则。例如,考虑 String,它自 Java 4 以来就有一个 contentEquals(StringBuffer)方法。在 Java 5 中,新增了一个 CharSequence 接口,用来为 StringBuffer,StringBuilder,String,CharBuffer 和其他类似的类型提供公共接口。在添加 CharSequence 接口的同时,String 也加(outfitted)了一个接受一个 CharSequence 类型参数的 contentEquals 方法。 -  虽然产生的重载明显违反了此项中的指导原则,但它不会造成任何损害,因为重载方法在同一对象引用上调用时会执行完全相同的操作。程序猿可能并不知道哪个重载函数会被调用,但是只要它们的行为相同,它【知道哪个重载函数会被调用】就没有任何意义。确保这种行为的标准做法是,让更具体化的重载方法把调用转发给更一般化的重载方法: +  虽然产生的重载明显违反了此项中的指导原则,但它不会造成任何损害,因为重载方法在同一对象引用上调用时会执行完全相同的操作。程序员可能并不知道哪个重载函数会被调用,但是只要它们的行为相同,它【知道哪个重载函数会被调用】就没有任何意义。确保这种行为的标准做法是,让更具体化的重载方法把调用转发给更一般化的重载方法: ```java // Ensuring that 2 methods have identical behavior by forwarding @@ -137,7 +137,7 @@ public boolean contentEquals(StringBuffer sb) {   虽然 Java 平台类库很大程度上遵循了本项中的建议,但是也有诸多的类违背了。例如:String 类导出了两个重载的静态工厂方法:valueOf(char\[\])和 valueOf(Object),当这两个方法被传递了同样的对象引用时,它们所做的事情完全不同。没有正当的理由可以解释这一点,它应该被看作是一种反常行为,有可能会造成真正的混淆。 -  简而言之,能够重载方法并不意味着就应该重载方法。一般情况下,对于多个具有相同参数数目的方法来说,应该尽量避免重载方法。在某些情况下,特别是涉及构造函数的时候,要遵循这条建议也许是不可能的。在这种情况下,至少应该避免这样的情形:同一组参数只需要经过类型转换就可以被传递给不用的重载方法。如果不能避免这种情形,例如,因为正在改造一个现有的类来实现新的接口,就应该保证:当传递同样的参数时,所有重载方法的行为必须一致。如果不能做到这一点,程序猿就很难有效地使用被重载的方法或者构造器,它们就不能理解它为什么不能正常地工作。 +  简而言之,能够重载方法并不意味着就应该重载方法。一般情况下,对于多个具有相同参数数目的方法来说,应该尽量避免重载方法。在某些情况下,特别是涉及构造函数的时候,要遵循这条建议也许是不可能的。在这种情况下,至少应该避免这样的情形:同一组参数只需要经过类型转换就可以被传递给不用的重载方法。如果不能避免这种情形,例如,因为正在改造一个现有的类来实现新的接口,就应该保证:当传递同样的参数时,所有重载方法的行为必须一致。如果不能做到这一点,程序员就很难有效地使用被重载的方法或者构造器,它们就不能理解它为什么不能正常地工作。 > - [第 51 项:谨慎设计方法签名](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第51项:谨慎设计方法签名.md) > - [第 53 项:慎用可变参数](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第08章:方法/第53项:慎用可变参数.md) diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" index 2b28105..a5747b7 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25454\351\241\271\357\274\232\350\277\224\345\233\236\351\225\277\345\272\246\344\270\272\351\233\266\347\232\204\346\225\260\347\273\204\346\210\226\350\200\205\351\233\206\345\220\210\357\274\214\350\200\214\344\270\215\346\230\257null.md" @@ -22,7 +22,7 @@ if (cheeses != null && cheeses.contains(Cheese.STILTON)) System.out.println("Jolly good, just the thing."); ``` -  对于一个返回 null 而不是零长度数组或者集合的方法,几乎每次用到该方法时都需要这种曲折的方式来处理。这样做很容易出错,因为编写客户端程序的程序猿可能会忘记写这种专门的代码来处理 null 返回值。这样的错误也许好几年都不会注意到,因为这样的方法通常返回一个或者多个对象。返回 null 而不是空的容器(empty container)也会使返回容器的方法的实现变得复杂。 +  对于一个返回 null 而不是零长度数组或者集合的方法,几乎每次用到该方法时都需要这种曲折的方式来处理。这样做很容易出错,因为编写客户端程序的程序员可能会忘记写这种专门的代码来处理 null 返回值。这样的错误也许好几年都不会注意到,因为这样的方法通常返回一个或者多个对象。返回 null 而不是空的容器(empty container)也会使返回容器的方法的实现变得复杂。   有时候会有人认为:null 返回值比空的容器或者数组更好,因为它避免了分配空容器所需要的开销。这种观点是站不住脚的,原因有两点。第一,担心这种级别的性能问题是不明智的,除非分析表明这个方法正是造成性能问题的真正源头(第 67 项)。第二,可以返回空集合和数组而不分配【空间给】它们。以下是返回可能为空的集合的典型代码。通常,这就是你所需要的: diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" index f18774c..3abc33a 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25455\351\241\271\357\274\232\350\260\250\346\205\216\350\277\224\345\233\236optional.md" @@ -1,6 +1,6 @@ ## 谨慎返回 optional -  在 Java 8 之前,在编写某些情况下无法返回值的方法时,可以采用两种方法。 你可以抛出异常,也可以返回 null(假设返回类型是对象引用类型)。这些方法都不完美。【出现】特殊的情况才应该保留异常(第 69 项),抛出异常【的成本】是很昂贵的,因为在创建异常时会捕获整个堆栈【的】跟踪【信息】。返回 null 没有这些缺点,但它有自己的缺点。如果方法返回 null,则客户端必须包含(include【使用】)特殊的代码以处理返回 null 的可能性,除非程序猿可以证明无法返回 null。如果客户端忽略检查空返回并在某些数据结构中存储空返回值,则 NullPointerException 可能在将来的某个任意时间的某个位置出现问题,而该位置与出现这个问题的根源不在同一个地方【这么翻译应该是没毛病的】(a NullPointerException may result at some arbitrary time in the future, at some place in the code that has nothing to do with the problem)。 +  在 Java 8 之前,在编写某些情况下无法返回值的方法时,可以采用两种方法。 你可以抛出异常,也可以返回 null(假设返回类型是对象引用类型)。这些方法都不完美。【出现】特殊的情况才应该保留异常(第 69 项),抛出异常【的成本】是很昂贵的,因为在创建异常时会捕获整个堆栈【的】跟踪【信息】。返回 null 没有这些缺点,但它有自己的缺点。如果方法返回 null,则客户端必须包含(include【使用】)特殊的代码以处理返回 null 的可能性,除非程序员可以证明无法返回 null。如果客户端忽略检查空返回并在某些数据结构中存储空返回值,则 NullPointerException 可能在将来的某个任意时间的某个位置出现问题,而该位置与出现这个问题的根源不在同一个地方【这么翻译应该是没毛病的】(a NullPointerException may result at some arbitrary time in the future, at some place in the code that has nothing to do with the problem)。   在 Java 8 中,有第三种方法来编写可能无法返回值的方法。Optional 类表示一个不可变容器,它可以包含单个非空 T 引用,也可以不包含任何内容。一个不包含任何内容的 optional 被认为是空的。在 optional 里存在一个值就可以认为是非空的(A value is said to be present in an optional that is not empty.)【大概、可能、也许、应该是这个意思吧】。一个 optional 本质上是一个可容纳最多一个元素的不可变的集合。Optional不是实现 Collection【接口】,但原则上是可以的。 diff --git "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" index b7faa0e..daca69c 100644 --- "a/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" +++ "b/\347\254\25408\347\253\240\357\274\232\346\226\271\346\263\225/\347\254\25456\351\241\271\357\274\232\344\270\272\346\211\200\346\234\211\345\257\274\345\207\272\347\232\204API\345\205\203\347\264\240\347\274\226\345\206\231\346\226\207\346\241\243\346\263\250\351\207\212.md" @@ -2,7 +2,7 @@   如果要想使一个 API 真正可用,就必须为其编写文档。传统意义上的 API 文档是手工生成的,所以保持文档与代码同步是一件很繁琐的事情。Java 编程环境提供了一种被成为 Javadoc 的实用工具。Javadoc 使用特殊格式的*文档注释(documentation comments)*(通常称为*doc 注释(doc comments)*)从源代码自动生成 API 文档。 -  虽然这些文档注释规范不是 Java 正式语言的一部分,但它们已经构成了每个程序猿都应该知道的 API。这些规范在*关于如何编写文档注释(How to Write Doc Comments)*的网站上进行了说明\[Javadocguide\]。虽然这个网站在 Java 4 发行之后就没有再进行更新了,但它仍然是个很有价值的资源。Java 9 中添加了一个重要的 doc 标签,{@index}; Java 8 中添加了一个,{@implSpec}; Java 5 中添加了两个,{@literal}和{@code}。上述网站中没有这些标签,但在此项中进行了【相关的】讨论。 +  虽然这些文档注释规范不是 Java 正式语言的一部分,但它们已经构成了每个程序员都应该知道的 API。这些规范在*关于如何编写文档注释(How to Write Doc Comments)*的网站上进行了说明\[Javadocguide\]。虽然这个网站在 Java 4 发行之后就没有再进行更新了,但它仍然是个很有价值的资源。Java 9 中添加了一个重要的 doc 标签,{@index}; Java 8 中添加了一个,{@implSpec}; Java 5 中添加了两个,{@literal}和{@code}。上述网站中没有这些标签,但在此项中进行了【相关的】讨论。   **为了正确地编写 API 文档,必须在每个被导出的类、接口、构造器、方法和域声明之前增加一个文档注释。** 如果类是可序列化的,也应该对它的序列化形式编写文档(第 87 项)。在没有文档注释的情况下,Javadoc 所能够做的也就是重新生成该声明,作为受影响的 API 元素的唯一文档。使用没有文档注释的 API 是非常痛苦的,也很容易出错。公共类不应使用默认构造函数,因为无法为它们提供文档注释。为了编写可维护的代码,你还应该为大多数未导出的类,接口,构造函数,方法和字段编写文档注释,尽管这些注释不需要像导出的 API 元素那样详细。 @@ -31,7 +31,7 @@ E get(int index); ``` -  注意,这份文档注释中使用了 HTML 标签(\

和\)。Javadoc 工具会把文档注释翻译成 HTML,文档注释中包含的任意 HTML 元素都会出现在生成的 HTML 文档中。有时候,程序猿会把 HTML 表格嵌入到它们的文档注释中,但是这种做法并不多见。 +  注意,这份文档注释中使用了 HTML 标签(\

和\)。Javadoc 工具会把文档注释翻译成 HTML,文档注释中包含的任意 HTML 元素都会出现在生成的 HTML 文档中。有时候,程序员会把 HTML 表格嵌入到它们的文档注释中,但是这种做法并不多见。   还要注意,@throws 子句的代码片段中到处使用了 Javadoc 的{@code}标签。它有两个作用:造成该代码片段以代码字体(code font)进行呈现,并限制 HTML 标记和嵌套的 Javadoc 标签在代码片段中进行处理。后一种属性证正是允许我们在代码片段中使用小于号(<)的东西,虽然它是一个 HTML 元字符。要在文档注释中包含多行代码示例,请使用包含在 HTML\

标记内的 Javadoc {@code}标记。换句话说,在代码示例之前加上字符\
{@code 代码跟在这后面}\
。这样可以保留代码中的换行符,并且不需要转义 HTML 元字符,而不需要转义符号(@),如果代码示例使用注释,则必须对其进行转义。
 
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md"
index 6196844..1adec92 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25457\351\241\271\357\274\232\345\260\206\345\261\200\351\203\250\345\217\230\351\207\217\347\232\204\344\275\234\347\224\250\345\237\237\346\234\200\345\260\217\345\214\226.md"
@@ -2,7 +2,7 @@
 
   本项与第 15 项(使类和成员的可访问性最小化)本质上是类似的。将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性。
 
-  较早的程序设计语言(如 C 语言)要求局部变量必须在一个代码块的开头处进行声明,出于习惯,有些程序猿目前还是继续这样做。这是个值得打破的习惯。在此提醒 Java 允许你在任何可以出现语句的地方声明变量(与 C 一样,自 C99 起)。
+  较早的程序设计语言(如 C 语言)要求局部变量必须在一个代码块的开头处进行声明,出于习惯,有些程序员目前还是继续这样做。这是个值得打破的习惯。在此提醒 Java 允许你在任何可以出现语句的地方声明变量(与 C 一样,自 C99 起)。
 
   **要使局部变量的作用域最小化,最有力的方法是在第一次使用它的地方声明** 。如果变量在使用之前进行声明,这只会造成混乱————对于试图理解程序功能的读者来说,这又多了一种只会分散他们注意力的因素。等到用到该变量的时候,读者可能已经记不起该变量的类型或者初始值了。
 
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md"
index c4600ab..6cbad17 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25458\351\241\271\357\274\232for-each\345\276\252\347\216\257\344\274\230\345\205\210\344\272\216\344\274\240\347\273\237\347\232\204for\345\276\252\347\216\257.md"
@@ -47,7 +47,7 @@ List deck = new ArrayList<>();
             deck.add(new Card(i.next(), j.next()));
 ```
 
-  如果之前没有发现这个 BUG 也不必难过。许多专家级的程序猿偶尔也会犯这样的错误。问题在于,在迭代器对外部的集合(suits)调用了太多次的 next 方法了。它应该从外部的循环进行调用,以便每种花色调用一次,但它却是从内部循环调用,因此它是每张牌调用一次。在用完所有花色之后,循环就会抛出 NoSuchElementException 异常。
+  如果之前没有发现这个 BUG 也不必难过。许多专家级的程序员偶尔也会犯这样的错误。问题在于,在迭代器对外部的集合(suits)调用了太多次的 next 方法了。它应该从外部的循环进行调用,以便每种花色调用一次,但它却是从内部循环调用,因此它是每张牌调用一次。在用完所有花色之后,循环就会抛出 NoSuchElementException 异常。
 
   如果真的那么不幸,并且外部集合的大小是内部集合大小的几倍————可能因为它们是相同的集合————循环就会正常终止,但是不会完成你想要的工作。例如,下面是个考虑不周的尝试,要打印一对骰子的所有可能的滚法:
 
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md"
index f7383c5..692cc4a 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25459\351\241\271\357\274\232\344\272\206\350\247\243\345\222\214\344\275\277\347\224\250\347\261\273\345\272\223.md"
@@ -1,6 +1,6 @@
 ## 了解和使用类库
 
-  假设你希望产生位于 0 和某个上界之间的随机整数。面对这个常见的任务,许多程序猿会编写如下所示的方法:
+  假设你希望产生位于 0 和某个上界之间的随机整数。面对这个常见的任务,许多程序员会编写如下所示的方法:
 
 ```java
 // Common but deeply flawed!
@@ -27,11 +27,11 @@ public static void main(String[] args) {
 
   random 方法的第三个缺点是,在极少数情况下,它的失败是灾难性的,返回一个落在指定范围之外的数。之所以如此,是因为这个方法试图通过调用 Math.abs,将 rnd.nextInt()返回的值映射为一个非负整数 int。假如 nextInt()返回 Integer.MIN_VALUE,那么 Math.abs 也会返回 Integer.MIN_VALUE,假设 n 不是 2 的乘方,那么取模操作符(%)将返回一个负数。这几乎肯定会使程序失败,而且这种失败很难重现。
 
-  为了编写能修正这三个缺点的 random 方法,有必要了解关于伪随机数生成器、数论和 2 的求补算法的相关知识。幸运的是,你并不需要自己来做这些工作————已经有现成的成果可以为你所用。它被称为 Random.nextInt(int),你无需关心它如何完成其工作的细节(如果你有强烈的好奇心,可以研究它的文档或者源代码)。具有算法背景的高级工程师已经花了大量的时间来设计、实现和测试这个方法,然后经过这个领域中的专家的审查,以确保它的正确性。然后,标准类库经过 Beta 测试、发行和将近二十年的成千上万程序猿的广泛使用。在这个方法中还没有发现过缺陷,但是,如果将来发现有缺陷,在下一个发行版本中就会修正这些缺陷。**通过使用标准类库,可以充分利用这些编写标准类库的专家的知识,以及在你之前的其他人的使用经验** 。
+  为了编写能修正这三个缺点的 random 方法,有必要了解关于伪随机数生成器、数论和 2 的求补算法的相关知识。幸运的是,你并不需要自己来做这些工作————已经有现成的成果可以为你所用。它被称为 Random.nextInt(int),你无需关心它如何完成其工作的细节(如果你有强烈的好奇心,可以研究它的文档或者源代码)。具有算法背景的高级工程师已经花了大量的时间来设计、实现和测试这个方法,然后经过这个领域中的专家的审查,以确保它的正确性。然后,标准类库经过 Beta 测试、发行和将近二十年的成千上万程序员的广泛使用。在这个方法中还没有发现过缺陷,但是,如果将来发现有缺陷,在下一个发行版本中就会修正这些缺陷。**通过使用标准类库,可以充分利用这些编写标准类库的专家的知识,以及在你之前的其他人的使用经验** 。
 
   从 Java 7 开始,你不应再使用 Random。对于大多数的用法,**选择的随机数生成器现在【首选】是 ThreadLocalRandom** 。它产生更高质量的随机数,而且速度非常快。在我的机器上,它比 Random 快 3.6 倍。对于 fork 连接池和并行流,请使用 SplittableRandom。
 
-  使用这些类库的第二个好处是,不必浪费时间为那些与工作不太相关的问题提供特别的解决方案。就像大多数程序猿一样,应该把时间花在应用程序上,而不是底层的细节上。
+  使用这些类库的第二个好处是,不必浪费时间为那些与工作不太相关的问题提供特别的解决方案。就像大多数程序员一样,应该把时间花在应用程序上,而不是底层的细节上。
 
   使用标准类库的第三个好处是,它们的性能往往会随着时间的推移而不断提高,无需你做任何努力。因为许多人在使用它们,被当作工业标准在使用,所以,提供这些标准类库的组织有强烈的动机要使它们运行得更快。这些年来,许多 Java 平台类库已经被重新编写了,有时候是重复编写,从而导致性能上有了显著的提高。
 
@@ -39,7 +39,7 @@ public static void main(String[] args) {
 
   使用标准类库的最后一个好处是,可以使自己的代码融入主流,这样的代码更易容阅读、更容易维护、更容易被大多数的开发人员重用。
 
-  既然有那么多的优点,使用标准类库机制而不选择专门的实现,这显然是符合逻辑的,然而还是有相当一部分的程序猿没有这样做。为什么呢?可能它们并不知道有这些类库机制的存在。**每个主要版本的库中都添加了许多功能,并且可以随时了解这些新增内容** 。每次 Java 平台有重要的发行版本时,会有一个网页说明新的特性。这些网页值得仔细地读一读\[Java8-feat, Java9-feat\]。为了强调这一点,假设你想编写一个程序来打印命令行中指定的 URL 的内容(这大致与 Linux curl 命令相同)。在 Java 9 之前,这段代码有点乏味,但在 Java 9 中,transferTo 方法被添加到 InputStream 中。以下是使用此新方法执行此任务的完整程序:
+  既然有那么多的优点,使用标准类库机制而不选择专门的实现,这显然是符合逻辑的,然而还是有相当一部分的程序员没有这样做。为什么呢?可能它们并不知道有这些类库机制的存在。**每个主要版本的库中都添加了许多功能,并且可以随时了解这些新增内容** 。每次 Java 平台有重要的发行版本时,会有一个网页说明新的特性。这些网页值得仔细地读一读\[Java8-feat, Java9-feat\]。为了强调这一点,假设你想编写一个程序来打印命令行中指定的 URL 的内容(这大致与 Linux curl 命令相同)。在 Java 9 之前,这段代码有点乏味,但在 Java 9 中,transferTo 方法被添加到 InputStream 中。以下是使用此新方法执行此任务的完整程序:
 
 ```java
 // Printing the contents of a URL with transferTo, added in Java 9
@@ -50,13 +50,13 @@ public static void main(String[] args) throws IOException {
 }
 ```
 
-  这些标准类库机制太庞大了,以至于不可能去学习所有的文档\[Java9-api\],但是**每个程序猿都应该熟悉 java.lang、java.util 和 java.io,以及它们的子包** 。可以根据需要获取其他类库的知识。总结类库的技巧超出了本项的范围,这些技巧多年来一直在增长。
+  这些标准类库机制太庞大了,以至于不可能去学习所有的文档\[Java9-api\],但是**每个程序员都应该熟悉 java.lang、java.util 和 java.io,以及它们的子包** 。可以根据需要获取其他类库的知识。总结类库的技巧超出了本项的范围,这些技巧多年来一直在增长。
 
-  有几个类库特别值得一提。集合框架和流类库(第 45 项-第 58 项)应该是每个程序猿的基本工具包的一部分,也包括 java.util.concurrent 中的并发实用工具。这个包即包含高级别的并发工具来简化多线程的编程任务,还包含低级别的并发类型,允许专家们自己编写更高级的并发抽象。第 80 和 81 项讨论了 java.util.current 的高级部分。
+  有几个类库特别值得一提。集合框架和流类库(第 45 项-第 58 项)应该是每个程序员的基本工具包的一部分,也包括 java.util.concurrent 中的并发实用工具。这个包即包含高级别的并发工具来简化多线程的编程任务,还包含低级别的并发类型,允许专家们自己编写更高级的并发抽象。第 80 和 81 项讨论了 java.util.current 的高级部分。
 
   有些情况下,一个类库工具并不能满足你的需要。你的需求越是特殊,这种情形就越有可能发生。虽然你的第一个念头应该是使用标准类库,但是,如果你在观察了它们在某些领域所提供的功能之后,确定它不能满足需要,那么就使用替代实现。任何有限的类库集提供的功能总是存在遗漏。如果你无法在 Java 平台库中找到所需要的内容,那么你的下一个选择应该是查看高质量的第三方库,例如 Google 优秀的开源 Guava 库\[Guava\]。如果你在任何适当的类库中都找不到所需要的功能,你可能只能自己实现,别无选择。
 
-  总而言之,不要重新发明轮子。如果你需要做的事情看起来是十分常见的,有可能类库中已经有某个类完成了这样的工作。如果确实是这样,就使用它;如果你不知道是否存在这样的类,就去查一查。一般而言,类库的代码可能比你自己编写的代码更好一些,并且会随着时间的推移不断改进。这并不是在影射你作为一只程序猿的能力。从经济角度的分析表明:类库代码受到的关注远远超过大多数普通程序猿在同样的功能上所能给予的投入。
+  总而言之,不要重新发明轮子。如果你需要做的事情看起来是十分常见的,有可能类库中已经有某个类完成了这样的工作。如果确实是这样,就使用它;如果你不知道是否存在这样的类,就去查一查。一般而言,类库的代码可能比你自己编写的代码更好一些,并且会随着时间的推移不断改进。这并不是在影射你作为一只程序员的能力。从经济角度的分析表明:类库代码受到的关注远远超过大多数普通程序员在同样的功能上所能给予的投入。
 
 > - [第 58 项:for-each 循环优先于传统的 for 循环](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第58项:for-each循环优先于传统的for循环.md)
 > - [第 60 项:如果需要精确的答案,请避免使用 float 和 double](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第09章:通用编程/第60项:如果需要精确的答案,请避免使用float和double.md)
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md"
index 3b4084c..f6ac8f5 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25461\351\241\271\357\274\232\345\237\272\346\234\254\347\261\273\345\236\213\344\274\230\345\205\210\344\272\216\350\243\205\347\256\261\345\237\272\346\234\254\347\261\273\345\236\213.md"
@@ -55,7 +55,7 @@ public static void main(String[] args) {
 
   这个程序运行起来比预计的要慢一些,因为它不小心将一个局部变量(sum)声明为是装箱基本类型 Long,而不是基本类型 long。程序编译起来没有错误或者警告,变量被反复地装箱和拆箱,导致明显的性能下降。
 
-  在本项中所讨论的这三个程序中,问题是一样的:程序猿忽略了基本类型和装箱基本类型之间的区别,并承受这些后果。在前面两个程序中,其结果是彻底的失败;在第三个程序中,则出现了服务器的性能问题。
+  在本项中所讨论的这三个程序中,问题是一样的:程序员忽略了基本类型和装箱基本类型之间的区别,并承受这些后果。在前面两个程序中,其结果是彻底的失败;在第三个程序中,则出现了服务器的性能问题。
 
   那么什么时候应该使用装箱基本类型呢?它们有几个合理的用处。第一个是作为集合中的元素、键和值。你不能将基本类型放在集合中,因此你被迫使用装箱基本类型。这是一种更通用的特例。在参数化类型(第 5 章)中,必须使用装箱基本类型作为参数类型,因为 Java 语言不允许使用基本类型。例如,你不能将变量声明为 ThreadLocal\类型。因此必须使用 ThreadLocal\代替。最后,在进行反射的方法调用(第 65 项)时,必须使用装箱基本类型。
 
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md"
index f41cd55..4c1d51e 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25462\351\241\271\357\274\232\345\246\202\346\236\234\345\205\266\344\273\226\347\261\273\345\236\213\346\233\264\351\200\202\345\220\210\357\274\214\345\210\231\345\260\275\351\207\217\351\201\277\345\205\215\344\275\277\347\224\250\345\255\227\347\254\246\344\270\262.md"
@@ -15,7 +15,7 @@ String compoundKey = className + "#" + i.next();
 
   这种方法有许多缺点。如果用来分隔域的字符也出现在某个域中,就会出现混乱。为了访问单独的域,必须解析该字符串,这个过程非常慢,也很繁琐,还容易出错。你无法提供 equals、toString 或者 compareTo 方法,但是却被迫接受 String 提供的行为。更好的做法是,简单地编写一个类来描述这个数据集,通常是一个私有的静态成员类(第 24 项)。
 
-  **字符串也不适合代替能力(capabilities)** 。有时候,字符串被用于对某种功能进行授权访问。例如,考虑设计一个线程局部变量(thread-local variable)的机制。这个机制提供的变量在每个线程中都有自己的值。自从 Java 1.2 发行版本以来,Java 类库就有提供线程局部变量的机制,但在那之前,程序猿必须自己完成。几年前面对这样的设计任务时,有些人自己提出了同样的设计方案:利用客户端提供的字符串键,对每个线程局部变量的内容进行访问授权:
+  **字符串也不适合代替能力(capabilities)** 。有时候,字符串被用于对某种功能进行授权访问。例如,考虑设计一个线程局部变量(thread-local variable)的机制。这个机制提供的变量在每个线程中都有自己的值。自从 Java 1.2 发行版本以来,Java 类库就有提供线程局部变量的机制,但在那之前,程序员必须自己完成。几年前面对这样的设计任务时,有些人自己提出了同样的设计方案:利用客户端提供的字符串键,对每个线程局部变量的内容进行访问授权:
 
 ```java
 // Broken - inappropriate use of string as capability!
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md"
index 75a962a..a23bde7 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25466\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\344\275\277\347\224\250\346\234\254\345\234\260\346\226\271\346\263\225.md"
@@ -6,7 +6,7 @@
 
   **使用本地方法来提高性能的这种做法并不提倡** 。在早期的发行版本中(在 Java 3 之前),这样做往往是很有必要的,但从那时起 JVM 就变得更快了。对于大多数任务,现在可以在 Java 中获得与之相当的性能。例如,当在 1.1 版中添加 java.math 时,BigInteger 依赖于用 C 编写的一个快速的多精度算术库。在 Java 3 中,BigInteger 在 Java 中重新实现,并仔细调整到比原来【依赖于】本地【库】实现【的版本】运行得更快的程度。
 
-  这个故事的一个令人遗憾的结论是 BigInteger 从那以后变化不大,除了 Java 8 中大数字的快速乘法。在那段时间,本机【代码】库的【优化】工作仍在继续,特别是 GNU 多精度算术库(GMP)。现在需要真正高性能多精度算术的 Java 程序猿通过本地方法\[Blum14\]使用 GMP 是合理的。
+  这个故事的一个令人遗憾的结论是 BigInteger 从那以后变化不大,除了 Java 8 中大数字的快速乘法。在那段时间,本机【代码】库的【优化】工作仍在继续,特别是 GNU 多精度算术库(GMP)。现在需要真正高性能多精度算术的 Java 程序员通过本地方法\[Blum14\]使用 GMP 是合理的。
 
   使用本地方法具有严重的缺点。由于本地语言是不安全的(第 50 项),使用本地方法的应用程序不再能免受内存损坏错误的影响。由于本地语言比 Java 更依赖于平台,因此使用本地方法的程序不再是可自由移植的。它们【使用本地方法的应用程序】也很难调试。如果你不小心,本地方法可能会降低性能,因为垃圾收集器无法自动化,甚至无法跟踪本机内存使用情况(第 8 项),并且在进入和退出本地代码时,需要相关的固定开销。最后,需要与本地方法进行“耦合的代码(glue code)”编写起来单调乏味,并且难以阅读。
 
diff --git "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md" "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md"
index 3462af0..4fca83f 100644
--- "a/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md"
+++ "b/\347\254\25409\347\253\240\357\274\232\351\200\232\347\224\250\347\274\226\347\250\213/\347\254\25468\351\241\271\357\274\232\351\201\265\345\256\210\346\231\256\351\201\215\346\216\245\345\217\227\347\232\204\345\221\275\345\220\215\346\203\257\344\276\213.md"
@@ -2,7 +2,7 @@
 
   Java 平台建立了一整套很好的*命名惯例(naming convention)*,其中有许多命名惯例包含在了《The Java Language Specification》[JLS, 6.1]中。不严格地讲,这些命名惯例分为两大类:字面的(typographical)和语法的(grammatical)。
 
-  字面的命名惯例比较少,涉及包、类、接口、方法、域和类型变量。应该尽量不违反这些惯例,没有很好的理由就绝不要违反它们。在这两种情况下,违反惯例都会潜在地给使用这些代码的其他程序猿带来困惑和苦恼,并且使他们做出错误的假设,造成程序出错。本项将对这些惯例做简要的介绍。
+  字面的命名惯例比较少,涉及包、类、接口、方法、域和类型变量。应该尽量不违反这些惯例,没有很好的理由就绝不要违反它们。在这两种情况下,违反惯例都会潜在地给使用这些代码的其他程序员带来困惑和苦恼,并且使他们做出错误的假设,造成程序出错。本项将对这些惯例做简要的介绍。
 
   包的名称应该是层次状的,用句号【英文句号】分隔每个部分。每个部分都包括小写字母和数字(很少使用数字)。任何将在你的组织之外使用的包,其名称都将以你的组织的 Internet 域名开头,并且顶级域名放在前面,例如 edu.cmu、com.google、org.eff。标准类库和一些可选的包,其名称以 java 和 javax 开头,这属于这一规则的例外。用户创建的包的名称绝不能以 java 和 javax 开头。可以在 JLS 中找到将 Internet 域名转换为包名称前缀的详细规则\[JLS, 6.1\]。
 
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md"
index b3f4baa..3aaae17 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25469\351\241\271\357\274\232\345\217\252\351\222\210\345\257\271\345\274\202\345\270\270\347\232\204\346\203\205\345\206\265\346\211\215\344\275\277\347\224\250\345\274\202\345\270\270.md"
@@ -12,7 +12,7 @@ try {
 }
 ```
 
-  这段代码有什么作用?看起来【这段代码的作用】并不明显,这就是不使用它的原因(第 67 项)。事实证明,这是一种用于循环遍历数组元素的非常有毛病的构想。当这个无限循环在尝试访问数组边界外的第一个数组元素时,用抛出(throw)、捕获(catch)、忽略 ArrayIndexOutOfBoundsException 异常的手段来达到终止无限循环的目的。假定它与数组循环的标准模式是等价的,对于任何一只 Java 程序猿来说,下面的标准模式一看就会明白:
+  这段代码有什么作用?看起来【这段代码的作用】并不明显,这就是不使用它的原因(第 67 项)。事实证明,这是一种用于循环遍历数组元素的非常有毛病的构想。当这个无限循环在尝试访问数组边界外的第一个数组元素时,用抛出(throw)、捕获(catch)、忽略 ArrayIndexOutOfBoundsException 异常的手段来达到终止无限循环的目的。假定它与数组循环的标准模式是等价的,对于任何一只 Java 程序员来说,下面的标准模式一看就会明白:
 
 ```java
 for (Mountain m : range)
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md"
index 1deacf5..0d1aca4 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25470\351\241\271\357\274\232\345\257\271\345\217\257\346\201\242\345\244\215\347\232\204\346\203\205\345\206\265\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270\357\274\214\345\257\271\347\274\226\347\250\213\351\224\231\350\257\257\344\275\277\347\224\250\350\277\220\350\241\214\346\227\266\345\274\202\345\270\270.md"
@@ -1,6 +1,6 @@
 ## 对可恢复的情况使用受检异常,对编程错误使用运行时异常
 
-  Java 程序设计语言提供了是三种可抛出的结构(throwable):_受检异常(checked exceptions)_,*运行时异常( runtime exceptions)*和*错误(error)*。在程序猿之间就存在一些困惑:什么时候适合使用哪种可抛出的结构。虽然做决定的界限并不总是那么清晰,但还是有一些一般性的原则提供了强有力的指导。
+  Java 程序设计语言提供了是三种可抛出的结构(throwable):_受检异常(checked exceptions)_,*运行时异常( runtime exceptions)*和*错误(error)*。在程序员之间就存在一些困惑:什么时候适合使用哪种可抛出的结构。虽然做决定的界限并不总是那么清晰,但还是有一些一般性的原则提供了强有力的指导。
 
   在决定使用受检异常或者未受检异常时,主要的原则是:**如果期望调用者能够适当地恢复【到正常状态】,对于这种情况就应该使用受检异常** 。通过抛出受检异常,强迫调用者在一个 catch 子句中处理该异常,或者将它传播出去。因此,方法中声明要抛出的每个受检异常,都是对 API 用户的一种潜在的指示:与异常相关联的条件是调用这个方法的一种可能的结果。
 
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md"
index 4b3e484..24bf8dc 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25471\351\241\271\357\274\232\351\201\277\345\205\215\344\270\215\345\277\205\350\246\201\345\234\260\344\275\277\347\224\250\345\217\227\346\243\200\345\274\202\345\270\270.md"
@@ -1,8 +1,8 @@
 ## 避免不必要地使用受检异常
 
-  很多 Java 程序猿不喜欢受检异常,但是使用得当的话,他们可以改善 API 和程序。与返回代码和未受检异常不同,它们强迫程序猿处理问题,提高了可靠性。也就是说,过分使用受检的异常会使 API 使用起来非常不方便。如果方法抛出一个或者多个受检的异常,调用该方法的代码就必须在一个或者多个 catch 块中处理这些异常,或者它必须声明它抛出这些异常,并让它们传播出去。无论哪种方法,它都会给使用 API 的用户带来负担。Java 8 中增加了这种负担,因为抛出受检异常的方法无法直接在流中使用(第 45-48 项)。
+  很多 Java 程序员不喜欢受检异常,但是使用得当的话,他们可以改善 API 和程序。与返回代码和未受检异常不同,它们强迫程序员处理问题,提高了可靠性。也就是说,过分使用受检的异常会使 API 使用起来非常不方便。如果方法抛出一个或者多个受检的异常,调用该方法的代码就必须在一个或者多个 catch 块中处理这些异常,或者它必须声明它抛出这些异常,并让它们传播出去。无论哪种方法,它都会给使用 API 的用户带来负担。Java 8 中增加了这种负担,因为抛出受检异常的方法无法直接在流中使用(第 45-48 项)。
 
-  如果正确地使用 API 并不能阻止这种异常条件的产生,并且一旦产生异常,使用 API 的程序猿可以立即采取有用的操作,这种负担就被认为是合理的。除非这两个条件都成立,否则更适合使用未受检的异常。作为一个“石蕊试纸”测试【简单而具有决定性的测试】,你可以试着问自己:程序猿将如何处理该异常。下面的做法是最好的吗?
+  如果正确地使用 API 并不能阻止这种异常条件的产生,并且一旦产生异常,使用 API 的程序员可以立即采取有用的操作,这种负担就被认为是合理的。除非这两个条件都成立,否则更适合使用未受检的异常。作为一个“石蕊试纸”测试【简单而具有决定性的测试】,你可以试着问自己:程序员将如何处理该异常。下面的做法是最好的吗?
 
 ```java
 } catch (TheCheckedException e) {
@@ -19,9 +19,9 @@
 }
 ```
 
-  如果程序猿无法做得更好,就调用未受检的异常。
+  如果程序员无法做得更好,就调用未受检的异常。
 
-  如果一个受检异常是由方法抛出的唯一受检异常,会给程序猿带来非常高的额外负担。如果这个方法还有其他的受检异常,则该方法必须出现在 try 块中,并且该异常最多需要另一个 catch 块。如果方法抛出单个受检异常,则此异常是该方法必须出现在 try 块中且不能直接在流中使用的唯一原因。在这种情况下,问问自己是否有办法避免受检异常,这么做是值得的。
+  如果一个受检异常是由方法抛出的唯一受检异常,会给程序员带来非常高的额外负担。如果这个方法还有其他的受检异常,则该方法必须出现在 try 块中,并且该异常最多需要另一个 catch 块。如果方法抛出单个受检异常,则此异常是该方法必须出现在 try 块中且不能直接在流中使用的唯一原因。在这种情况下,问问自己是否有办法避免受检异常,这么做是值得的。
 
   消除受检异常的最简单方法是返回所需结果类型的 optional(第 55 项)。该方法只返回一个空的 optional,而不是抛出一个受检异常。该技巧的缺点在于该方法不能返回任何附加信息来详细说明其无法执行所需要的计算。相反,异常类型具有描述性,并且可以为导出的方法提供附加信息(第 70 项)。
 
@@ -47,7 +47,7 @@ if (obj.actionPermitted(args)) {
 }
 ```
 
-  这种重构并不总是恰当的,但是,凡是在恰当的地方,它都会使 API 用起来更加舒服。虽然后者的调用序列没有前者的漂亮,但是这样得到的 API 更加灵活。如果程序猿知道调用将会成功,或者不介意由于调用失败而导致的线程终止,这种重构还允许以下这个更为简单的调用形式:
+  这种重构并不总是恰当的,但是,凡是在恰当的地方,它都会使 API 用起来更加舒服。虽然后者的调用序列没有前者的漂亮,但是这样得到的 API 更加灵活。如果程序员知道调用将会成功,或者不介意由于调用失败而导致的线程终止,这种重构还允许以下这个更为简单的调用形式:
 
 ```java
 obj.action(args)
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md"
index b5f64be..54ef7b9 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25472\351\241\271\357\274\232\344\274\230\345\205\210\344\275\277\347\224\250\346\240\207\345\207\206\347\232\204\345\274\202\345\270\270.md"
@@ -1,10 +1,10 @@
 ## 优先使用标准的异常
 
-  专家级程序猿与缺乏经验的程序猿【菜猿】一个最主要的区别在于,专家追求并且通常也能够实现高度的代码重用。代码重用是值得提倡的,这是一条规则,异常也不例外。Java 平台的类库提供了一组基本的未受检异常,它们满足了绝大多数 API 抛出的所需要的异常。
+  专家级程序员与缺乏经验的程序员【菜猿】一个最主要的区别在于,专家追求并且通常也能够实现高度的代码重用。代码重用是值得提倡的,这是一条规则,异常也不例外。Java 平台的类库提供了一组基本的未受检异常,它们满足了绝大多数 API 抛出的所需要的异常。
 
-  重用现有的异常有多方面的好处。其中最主要的好处是,它使你的 API 更加易于学习和使用,因为它与程序猿已经熟悉的习惯用法是一致的。第二个好处是,对于用到这些 API 的程序而言,它们的可读性会更好,因为它们不会出现很多程序猿不熟悉的异常。最后(也是最不重要的)一点是,异常类越少,意味着内存印迹(footprint)【异常堆栈】就越小,装载这些类的时间开销也越少。
+  重用现有的异常有多方面的好处。其中最主要的好处是,它使你的 API 更加易于学习和使用,因为它与程序员已经熟悉的习惯用法是一致的。第二个好处是,对于用到这些 API 的程序而言,它们的可读性会更好,因为它们不会出现很多程序员不熟悉的异常。最后(也是最不重要的)一点是,异常类越少,意味着内存印迹(footprint)【异常堆栈】就越小,装载这些类的时间开销也越少。
 
-  最经常被重用的异常是 IllegalArgumentException。当调用者传递的参数值不合适的时候,往往就会抛出这个异常。例如,假设一个参数代表了“某个动作重复的次数”,如果程序猿给这个参数传递了一个负数,就会抛出这个异常。
+  最经常被重用的异常是 IllegalArgumentException。当调用者传递的参数值不合适的时候,往往就会抛出这个异常。例如,假设一个参数代表了“某个动作重复的次数”,如果程序员给这个参数传递了一个负数,就会抛出这个异常。
 
   另一个经常被重用的异常是 IllegalStateException。因为接收对象的状态【不这却】而导致调用非法,通常就会抛出这个异常。例如,如果在某个对象被正确地初始化之前,调用者就企图使用这个对象,就会抛出这个异常。
 
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md"
index b4f55c9..4f0b3b8 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25474\351\241\271\357\274\232\346\257\217\344\270\252\346\226\271\346\263\225\346\212\233\345\207\272\347\232\204\346\211\200\346\234\211\345\274\202\345\270\270\351\203\275\350\246\201\345\273\272\347\253\213\346\226\207\346\241\243.md"
@@ -2,13 +2,13 @@
 
   描述一个方法所抛出的异常,是正确使用这个方法时所需文档的重要组成部分。因此,花点时间仔细地为每个方法抛出的异常建立文档是特别重要的(第 56 项)。
 
-  **始终要单独地声明受检的异常,并且利用 Javadoc 的@throws 标记,准确地记录下抛出每个异常的条件** 。如果一个方法可能抛出多个异常类,则不要使用“快捷方式(shortcut)”声明它会抛出这些异常类的某个超类。永远不要声明一个方法“throws Exception”,或者更糟糕的是声明它“throws Throwable”,这是非常极端的例子。这样的声明不仅没有为程序猿提供关于“这个方法能够抛出哪些异常”的任何指导信息,而且大大地妨碍了该方法的使用,因为它实际上掩盖了该方法在同样的执行环境下可能抛出的任何其他异常。这个建议的一个例外是 main 方法,它可以安全地声明为抛出 Exception,因为它只由 VM 调用。
+  **始终要单独地声明受检的异常,并且利用 Javadoc 的@throws 标记,准确地记录下抛出每个异常的条件** 。如果一个方法可能抛出多个异常类,则不要使用“快捷方式(shortcut)”声明它会抛出这些异常类的某个超类。永远不要声明一个方法“throws Exception”,或者更糟糕的是声明它“throws Throwable”,这是非常极端的例子。这样的声明不仅没有为程序员提供关于“这个方法能够抛出哪些异常”的任何指导信息,而且大大地妨碍了该方法的使用,因为它实际上掩盖了该方法在同样的执行环境下可能抛出的任何其他异常。这个建议的一个例外是 main 方法,它可以安全地声明为抛出 Exception,因为它只由 VM 调用。
 
-  虽然 Java 语言本身并不要求程序猿为一个方法声明它可能会抛出的未受检异常,但是,如同受检异常一样,仔细地为它们建立文档是非常明智的。未受检的异常通常代表编程上的错误(第 70 项),让程序猿了解这些错误有助于帮助他们避免犯这样的错误。对于方法可能抛出的未受检异常,如果将这些异常信息很好地组织成列表文档,就可以有效地描述出这个方法被成功执行的前提条件(precondition)。每个方法的文档应该描述它的前提条件(第 56 项),并在文档中记录下未受检的异常是满足此要求的最佳方式。
+  虽然 Java 语言本身并不要求程序员为一个方法声明它可能会抛出的未受检异常,但是,如同受检异常一样,仔细地为它们建立文档是非常明智的。未受检的异常通常代表编程上的错误(第 70 项),让程序员了解这些错误有助于帮助他们避免犯这样的错误。对于方法可能抛出的未受检异常,如果将这些异常信息很好地组织成列表文档,就可以有效地描述出这个方法被成功执行的前提条件(precondition)。每个方法的文档应该描述它的前提条件(第 56 项),并在文档中记录下未受检的异常是满足此要求的最佳方式。
 
   对于接口中的方法,在文档中记录下它可能抛出的未受检异常显得尤为重要。这份文档构成了该接口*通用约定(general contract)*的一部分,它指定了该接口的多个实现必须遵循的公共行为。
 
-  **使用 Javadoc 的@throws 标签记录下一个方法可能抛出的每个未受检异常,但是不要在未受检异常上使用 throws 关键字** 。使用 API 的程序猿必须知道哪些异常是需要受检的,哪些是不需要受检的,这很重要,因为这两种情况下他们【程序猿】的责任是不同的。由 Javadoc @throws 标记生成的文档在方法声明中没有相应的 throws 子句,这就为程序猿提供了一个强大的提示信息,即:这是一个未受检异常。
+  **使用 Javadoc 的@throws 标签记录下一个方法可能抛出的每个未受检异常,但是不要在未受检异常上使用 throws 关键字** 。使用 API 的程序员必须知道哪些异常是需要受检的,哪些是不需要受检的,这很重要,因为这两种情况下他们【程序员】的责任是不同的。由 Javadoc @throws 标记生成的文档在方法声明中没有相应的 throws 子句,这就为程序员提供了一个强大的提示信息,即:这是一个未受检异常。
 
   应该注意到的一点是,为每个方法可能抛出的所有未受检异常建立文档是很理想的,但是在实践中并非总能做到【理想很美好,现实很骨感】。当类被修订之后,如果有个导出方法被修改了,它将会抛出额外的未受检异常,这不算违反源代码或者二进制兼容性。假设一个类调用了另一个独立类中的方法。第一个类的编写者可能会为每个方法抛出的未受检异常仔细地建立文档,但是,如果第二个类被修订了,抛出了额外的未受检异常,很有可能第一个类(它并没有被修订)就会把新的未受检异常传播出去,尽管它并没有声明这些异常。
 
diff --git "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md" "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md"
index 5f4ada7..7ff606b 100644
--- "a/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md"
+++ "b/\347\254\25410\347\253\240\357\274\232\345\274\202\345\270\270/\347\254\25475\351\241\271\357\274\232\345\234\250\350\257\246\347\273\206\344\277\241\346\201\257\344\270\255\345\214\205\345\220\253\346\215\225\350\216\267\347\232\204\345\244\261\350\264\245\344\277\241\346\201\257.md"
@@ -1,8 +1,8 @@
 ## 在详细信息中包含捕获的失败信息
 
-  当程序由于未被捕获的异常而失败的时候,系统会自动地打印出该异常的栈跟踪信息。在栈跟踪信息中包含该异常的*字符串表示法(string represention)*,即它的 toString 方法的调用结果。它通常包含该异常的类名,紧随其后的是*详细信息(detail message)*。通常,这只是程序猿或者站点可靠性工程师【运维工程师?】(field service personnel,检查软件失败的人)在调查软件失败原因时必须检查的信息。如果失败的情形不容易重现,要想获得更多的信息会非常困难,甚至是不可能的。因此,异常类型的 toString 方法应该尽可能多地返回有关失败原因的信息,这一点特别重要。换句话说,异常的详细信息应该*捕获住失败(capture the failure)*,以便于以后分析。
+  当程序由于未被捕获的异常而失败的时候,系统会自动地打印出该异常的栈跟踪信息。在栈跟踪信息中包含该异常的*字符串表示法(string represention)*,即它的 toString 方法的调用结果。它通常包含该异常的类名,紧随其后的是*详细信息(detail message)*。通常,这只是程序员或者站点可靠性工程师【运维工程师?】(field service personnel,检查软件失败的人)在调查软件失败原因时必须检查的信息。如果失败的情形不容易重现,要想获得更多的信息会非常困难,甚至是不可能的。因此,异常类型的 toString 方法应该尽可能多地返回有关失败原因的信息,这一点特别重要。换句话说,异常的详细信息应该*捕获住失败(capture the failure)*,以便于以后分析。
 
-  **为了捕获失败,异常的详细信息应该包含所有“对该异常有贡献”【触发该异常】的参数和域的值** 。例如,IndexOutOfBoundsException 异常的详细信息应该包含下界、上界以及没有落在界内的下标值。该详细信息提供了许多关于失败的信息。这三个值中任何一个或者全部都有可能是错误的。实际的下标值可能小于下界或者等于上界(“越界错误”),或者它可能是个无效值,太小或太大。下界也有可能大于上界(严重违反内部约束条件的一种情况)。每一种情形都代表了不同的问题,如果程序猿知道应该去查找哪种错误,它【异常的详细信息】对诊断【错误】的帮助是很大的。
+  **为了捕获失败,异常的详细信息应该包含所有“对该异常有贡献”【触发该异常】的参数和域的值** 。例如,IndexOutOfBoundsException 异常的详细信息应该包含下界、上界以及没有落在界内的下标值。该详细信息提供了许多关于失败的信息。这三个值中任何一个或者全部都有可能是错误的。实际的下标值可能小于下界或者等于上界(“越界错误”),或者它可能是个无效值,太小或太大。下界也有可能大于上界(严重违反内部约束条件的一种情况)。每一种情形都代表了不同的问题,如果程序员知道应该去查找哪种错误,它【异常的详细信息】对诊断【错误】的帮助是很大的。
 
   一个警告涉及安全的敏感信息。由于许多人在诊断和修复软件问题的过程中可能会看到栈跟踪信息,因此请**不要在详细信息中包含密码,加密密钥等** 。
 
@@ -30,9 +30,9 @@ public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {
 }
 ```
 
-  从 Java 9 开始,IndexOutOfBoundsException 最终获得了一个带有 int 值索引参数的构造函数,但遗憾的是它省略了 lowerBound 和 upperBound 参数。更一般地说,Java 类库并没有大量使用这个习惯用法,但强烈建议使用它。它使程序员很容易【通过】抛出【的】异常来捕获失败。事实上,这种做法使程序猿不想捕获失败都难!实际上,这种做法可以有效地把代码集中起来放在异常类中,由这些代码对异常类自身中的异常产生高质量的详细信息,而不是要求类的每个用户都多余地产生详细信息。
+  从 Java 9 开始,IndexOutOfBoundsException 最终获得了一个带有 int 值索引参数的构造函数,但遗憾的是它省略了 lowerBound 和 upperBound 参数。更一般地说,Java 类库并没有大量使用这个习惯用法,但强烈建议使用它。它使程序员很容易【通过】抛出【的】异常来捕获失败。事实上,这种做法使程序员不想捕获失败都难!实际上,这种做法可以有效地把代码集中起来放在异常类中,由这些代码对异常类自身中的异常产生高质量的详细信息,而不是要求类的每个用户都多余地产生详细信息。
 
-  正如第 70 项中所建议的,为捕获的异常的失败(failure-capture)的信息提供一些访问方法是合适的(在上述例子中的 lowerBound、upperBound 和 index 方法)。相对于未受检异常,未受检异常提供这样的访问方法更为重要,因为捕获失败的信息对于【将程序】从失败中恢复【正常】是非常有用的。程序猿希望通过程序的手段来访问未受检异常的细节,这很少见(尽管也是可以想象得到的)。然而,即使对于未受检的异常,作为一般原则提供这些访问方法也是明智的(第 12 项,原书 57 页)。
+  正如第 70 项中所建议的,为捕获的异常的失败(failure-capture)的信息提供一些访问方法是合适的(在上述例子中的 lowerBound、upperBound 和 index 方法)。相对于未受检异常,未受检异常提供这样的访问方法更为重要,因为捕获失败的信息对于【将程序】从失败中恢复【正常】是非常有用的。程序员希望通过程序的手段来访问未受检异常的细节,这很少见(尽管也是可以想象得到的)。然而,即使对于未受检的异常,作为一般原则提供这些访问方法也是明智的(第 12 项,原书 57 页)。
 
 > - [第 74 项:每个方法抛出的所有异常都要建立文档](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第74项:每个方法抛出的所有异常都要建立文档.md)
 > - [第 76 项:努力使失败保持原子性](https://gitee.com/tilerlgt/effective-java-third-edition/blob/master/第10章:异常/第76项:努力使失败保持原子性.md)
diff --git "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md" "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md"
index 197cac3..8cdd211 100644
--- "a/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md"
+++ "b/\347\254\25411\347\253\240\357\274\232\345\271\266\345\217\221/\347\254\25478\351\241\271\357\274\232\345\220\214\346\255\245\350\256\277\351\227\256\345\205\261\344\272\253\347\232\204\345\217\257\345\217\230\346\225\260\346\215\256.md"
@@ -1,6 +1,6 @@
 ## 同步访问共享的可变数据
 
-  关键字 synchronized 可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块。许多程序猿把同步的概念仅仅理解为一种*互斥的方式(mutual exclusion)*,即,当一个对象被一个线程修改的时候,可以阻止另一个线程观察到对象内部不一致的状态。按照这种观点,对象被创建的时候处于一致的状态(第 17 项),当有方法访问它的时候,它就被锁定了。这些方法观察到对象的状态,并且可能会引起状态转变(state transition),即把对象从一种一致的状态转换到另一种一致的状态。正确地使用同步可以保证没有任何方法会看到对象处于不一致的状态中。
+  关键字 synchronized 可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块。许多程序员把同步的概念仅仅理解为一种*互斥的方式(mutual exclusion)*,即,当一个对象被一个线程修改的时候,可以阻止另一个线程观察到对象内部不一致的状态。按照这种观点,对象被创建的时候处于一致的状态(第 17 项),当有方法访问它的时候,它就被锁定了。这些方法观察到对象的状态,并且可能会引起状态转变(state transition),即把对象从一种一致的状态转换到另一种一致的状态。正确地使用同步可以保证没有任何方法会看到对象处于不一致的状态中。
 
   这种观点是正确的,但它只说出了同步的一半意义。如果没有同步,一个线程的变化就不能被其他线程看到。同步不仅可以阻止一个线程看到对象处于不一致的状态之中,它还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护的之前所有的修改效果。
 
@@ -8,7 +8,7 @@
 
   你可能听说过,为了提高性能,在读写原子数据的时候,应该避免使用同步。这个建议是非常危险而错误的。虽然语言规范保证了线程在读取原子数据的时候,不会看到任意的数值,但是它并不保证一个线程写入的值对另一个线程将是可见的。**为了在线程之间进行可靠的通信,也为了互斥访问,同步是必要的** 。这主要是因为 Java 语言规范中的*内存模型(memory model)*,它规定了一个线程所做的变化何时以及如何变成对其他线程可见\[JLS, 17.4; Goetz06, 16\]。
 
-  如果对共享的可变数据的访问不能同步,其后果将非常可怕,即使这个变量是的读写是原子的。考虑下面这个在一个线程中将另一个线程终止(stop)的任务。Java 类库中提供了 Thread.stop 方法,但是这个方法在很久以前就不提倡使用了,因为它本质上是不安全的——使用它会导致数据遭到破坏。**不要使用 Thread.stop** 。要在一个线程终止另一个线程,建议的做法是让第一个线程轮询(poll)一个 boolean 域,这个域一开始为 false,但是可以通过第二个线程设置为 true,这样来表示第一个线程要终止自己。由于 boolean 域的读和写操作都是原子的,程序猿在访问这个域的时候不再使用同步。
+  如果对共享的可变数据的访问不能同步,其后果将非常可怕,即使这个变量是的读写是原子的。考虑下面这个在一个线程中将另一个线程终止(stop)的任务。Java 类库中提供了 Thread.stop 方法,但是这个方法在很久以前就不提倡使用了,因为它本质上是不安全的——使用它会导致数据遭到破坏。**不要使用 Thread.stop** 。要在一个线程终止另一个线程,建议的做法是让第一个线程轮询(poll)一个 boolean 域,这个域一开始为 false,但是可以通过第二个线程设置为 true,这样来表示第一个线程要终止自己。由于 boolean 域的读和写操作都是原子的,程序员在访问这个域的时候不再使用同步。
 
 ```java
 // Broken! - How long would you expect this program to run?
diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md"
index 9543fdb..3a072b4 100644
--- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md"
+++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25485\351\241\271\357\274\232\345\205\266\344\273\226\345\272\217\345\210\227\345\214\226\344\274\230\345\205\210\344\272\216Java\345\272\217\345\210\227\345\214\226.md"
@@ -1,6 +1,6 @@
 ## 其他序列化优先于 Java 序列化
 
-  当序列化在 1997 年被添加到 Java 时,它被认为有点风险的。该方法已经在一种研究语言(Modula-3)中尝试过,但在生产中的语言中从未用过。虽然程序猿承诺在分布式对象上付出点努力得到的成果是很有吸引力的,代价是构造函数是不可见的而且它的 API 和实现之间的界限很模糊,在正确性、性能、安全性和维护方面可能存在问题。支持者认为这些好处【前面的成果】超过了风险,但历史已经证明并不是这样的。
+  当序列化在 1997 年被添加到 Java 时,它被认为有点风险的。该方法已经在一种研究语言(Modula-3)中尝试过,但在生产中的语言中从未用过。虽然程序员承诺在分布式对象上付出点努力得到的成果是很有吸引力的,代价是构造函数是不可见的而且它的 API 和实现之间的界限很模糊,在正确性、性能、安全性和维护方面可能存在问题。支持者认为这些好处【前面的成果】超过了风险,但历史已经证明并不是这样的。
 
   本书前几版中描述的安全问题与某些人担心的一样严重。2000 年代早期讨论的小漏洞在接下来的十年被转化为严重的漏洞并被利用了,其中包括对旧金山都市交通局市政铁路(SFMTA Muni)的勒索软件攻击,该铁路在 2016 年 11 月关闭整个收费系统两天\[Gallagher16\]。
 
diff --git "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md" "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md"
index 2443d5a..a672c02 100644
--- "a/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md"
+++ "b/\347\254\25412\347\253\240\357\274\232\345\272\217\345\210\227\345\214\226/\347\254\25486\351\241\271\357\274\232\350\260\250\346\205\216\345\234\260\345\256\236\347\216\260Serializable\346\216\245\345\217\243.md"
@@ -1,6 +1,6 @@
 ## 谨慎地实现 Serializable 接口
 
-  要想使一个类的实例可被序列化,非常简单,只要在它的声明中加入“implemants Serializable”字样即可。正因为太容易了,所以普遍存在这样一种误解,认为程序猿可以毫不费力就可以实现序列化。实际情形要复杂得多。虽然使一个类可序列化的直接成本可以忽略不计,但长期的成本通常是很高的。
+  要想使一个类的实例可被序列化,非常简单,只要在它的声明中加入“implemants Serializable”字样即可。正因为太容易了,所以普遍存在这样一种误解,认为程序员可以毫不费力就可以实现序列化。实际情形要复杂得多。虽然使一个类可序列化的直接成本可以忽略不计,但长期的成本通常是很高的。
 
   **实现 Serializable 接口而付出的最大代价是,一旦一个类被发布,就大大降低了“改变这个类的实现”的灵活性** 。当一个类实现了 Serializable 接口,它的字节流编码(或者说*序列化形式(serialized form)*)就变成了它的导出的 API 的一部分。一旦这个类被广泛使用,往往必须永远支持这种序列化形式,就好像你必须要支持导出的 API 的所有其他部分一样。如果你不努力设计一种*自定义的序列化形式(custom serialized form)*,而仅仅接受了默认的序列化形式,这种序列化形式将永远地束缚在该类最初的内部表示法上。换句话说,如果你接受了默认的序列化形式,这个类中私有的和包级私有的实例域都将变成导出的 API 的一部分,这不符合“将域的访问权限限制到最低”的实践准则(第 15 项),因此,将它【除了 public 以外的权限修饰符】作为信息隐藏工具,它就失去了有效性。
 
-- 
Gitee