![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
跟我学(Effective Java 2)
文章平均质量分 86
Dullon_jiang
这个作者很懒,什么都没留下…
展开
-
跟我学(Effective Java 2)第63条:在细节消息中包含能捕获失败的信息
第63条:在细节消息中包含能捕获失败的信息当程序由于未被捕获的异常而失败的时候,系统会自动打印该异常的信息,在堆栈中包含该异常的字符串表示法,即它的toString方法的调用结果,包含了一系列信息:该异常的类名和细节消息。通常,这是程序员在调查程序失败原因的必要的信息。如果这个失败不易重现,这失败的信息就异常重要,异常的细节消息应该捕获住失败,便于以后分析。为了捕获失败,异常的细节信息应该包含...原创 2019-06-18 17:57:39 · 155 阅读 · 0 评论 -
跟我学(Effective Java 2)第73条:避免使用线程组
第73条:避免使用线程组除了线程、锁、监视器外,系统还提供了一个基本的抽象,即线程组(thread group)。线程组的目的是作为一种隔离applet(小程序)的机制,但实际上却没达到这个目的。它没有提供线程安全性功能,而是 允许同时把线程的某些基本功能应用到一组线程上,基本上已经废弃了。从线程安全性的角度来看,ThreadGroup API非常弱。为了得到一个线程组中的活动线程列表,你必须...原创 2019-06-20 17:53:06 · 212 阅读 · 0 评论 -
跟我学(Effective Java 2)第13条:使类和成员的可访问性最小化
第13条:使类和成员的可访问性最小化区别设计良好的模块和设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节。设计良好的模块会隐藏所有的实现细节,把它的API于它的实现清晰地隔离开来。然后,模块之间通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏(information hiding)或封装(encapsula...原创 2019-06-04 18:18:35 · 168 阅读 · 0 评论 -
跟我学(Effective Java 2)第14条:在公有类中使用访问方法而非公有域
第14条:在公有类中使用访问方法而非公有域有时候、可能会编写一些退化类(degenerate classes),没有什么作用,只是用来集中实例域:class Point { public double x; public double y;}由于这种类的数据是可以直接被访问的,这些类没有提供封装(encapsulation)的功能。如果不改变API,就无法改变它的数据表...原创 2019-06-04 18:29:53 · 170 阅读 · 0 评论 -
跟我学(Effective Java 2)第15条:使可变性最小化
第15条:使可变性最小化不可变类只是其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个生命周期(lifetime)内固定不变。Java平台包含的不可变类:String、基本类型的包装类、BigInteger、BigDecimal。不可变类比可变类更容易设计、实现和使用。为了使类成为不可变,要遵循以下五条规则:1、不要提供任何可以改变成员变量值的方法;...原创 2019-06-04 18:49:51 · 205 阅读 · 0 评论 -
跟我学(Effective Java 2)第16条:复合优先于继承
第16条:复合优先于继承继承是实现代码重用的有力手段,但是使用不当会导致软件变得脆弱。使用不当会导致软件变得很脆弱。在包的内部使用继承是非常安全的,在那里,子类和超类的实现都处在同一个程序员的控制之下。对于专门为了继承而设计、并且具有很好的文档说明的类来说,使用继承也是非常安全的。然而对于普通的具体类进行跨越包边界的继承,则是非常危险的。“继承”在这里特指实现继承。非接口继承。与方法调用不同的...原创 2019-06-04 19:05:21 · 143 阅读 · 0 评论 -
跟我学(Effective Java 2)第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
第17条:要么为继承而设计,并提供文档说明,要么就禁止继承首先,该类的文档必须精确地描述覆盖每个方法所带来的影响。换句话说,该类必须有文档说明他可覆盖(overridable)的方法的自用型(self-use)。对于每个共有的或受保护的方法或构造器,他的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的。更一般的,类必须在文档中说明...原创 2019-06-04 19:23:19 · 193 阅读 · 0 评论 -
跟我学(Effective Java 2)第33条:用EnumMap代替序数索引
第33条:用EnumMap代替序数索引有时候我们会利用ordinal方法来索引数组的代码。例如下面这个简化的类,表示一种烹饪用的香草:/** * 33 用EnumMap代替序数索引 */public class EnumMapTest { static class Herb { public enum Type { ANNUAL, PERENNIAL,...原创 2019-06-11 17:53:48 · 181 阅读 · 0 评论 -
跟我学(Effective Java 2)第34条:用接口模拟可伸缩的枚举
第34条:用接口模拟可伸缩的枚举虽然枚举类型是不可扩展的,但是接口类型则是可扩展的。它是用来表示API中的操作的接口类型。可以定义另一个枚举类型,它实现这个接口,并用新的类型的实例代替基本类型。/** * 34:用接口模拟可伸缩的枚举 * 枚举类型是不可扩展的,但是接口类型是可扩展的。使用接口,可以模拟可伸缩的枚举。 */public class EnumInterface { ...原创 2019-06-11 18:06:11 · 181 阅读 · 0 评论 -
跟我学(Effective Java 2)第72条:不要依赖于线程调度器
第72条:不要依赖于线程调度器当有多个线程可以运行时,由线程调度器(thread scheduler)决定哪些线程将会运行,以及运行多长时间。任何一个合理的操作系统在做出这样的决定时,都会努力做到公正,但是所采用的策略却大相径庭。因此,编写良好的程序不应该依赖于这种策略的细节。任何依赖于线程调度器来达到正确性或者性能要求的程序,很有可能都是不可移植的。要编写健壮的、响应良好的、可移植的多线程应...原创 2019-06-20 17:50:44 · 187 阅读 · 0 评论 -
跟我学(Effective Java 2)第71条:慎用延迟初始化
第71条:慎用延迟初始化延迟初始化(lazy initialization)是延迟到需要域的值时才将它初始化的这种行为。如果 永远不需要这个值,这个域就永远不会被初始化。这种方法既适用于静态域,也适用于实例域。虽然延迟初始化主要是一种优化,但它也可以用来打破类和实例初始化中的有害循环。就像大多数的优化一样,对于延迟初始化,最好建议“除非绝对必要,否则就不要这么做”( 见第55条:谨慎的进行优化...原创 2019-06-20 17:46:48 · 166 阅读 · 0 评论 -
跟我学(Effective Java 2)第68条:executor和task优先于线程
第68条:executor和task优先于线程在Java 1.5 发行版本中,Java平台中增加了java.util.concurrent。这个包中包含了Executor Framework,这是一个很灵活的基于接口的任务执行工具。它创建了一个在各方面都比工作队列更好,却只需要这一行代码:ExecutorService executor = Executors.newSingleThreadE...原创 2019-06-19 18:41:52 · 172 阅读 · 0 评论 -
跟我学(Effective Java 2)第28条:利用有限制通配符来提升API灵活性
第28条:利用有限制通配符来提升API灵活性参数化类型是 不可变的(invariant)。换句话说,对于任何两个截然不同的类型tyle1和type2来说,List既不是List的子类型,也不是他的超类型。虽然List不是List的子类型,这与直觉相悖,但是实际上很有意义。你可以将任何对象放进一个List中,却只能将字符串放进中。有时候,我需要的灵活性要比不可变类型所能提供的更多。public...原创 2019-06-10 18:02:38 · 128 阅读 · 0 评论 -
跟我学(Effective Java 2)第29条:优先考虑类型安全的异构容器
第29条:优先考虑类型安全的异构容器泛型最常用于集合,它充当被参数化的容器,这样就限制你每个容器只能有固定数目的类型参数。一般来说,这正是你想要的。但是,有的时候,我们需要更多的灵活性,比如,我们想安全的访问数据库的所有列,有一种方法可以容易做到这一点。这种想法是将键(key)进行参数化而不是将容器进行参数化。然后将参数化的键交给容器,来插入或者获取值。用泛型系统来确保值的类型与它的键相符。...原创 2019-06-10 18:27:37 · 139 阅读 · 0 评论 -
跟我学(Effective Java 2)第30条:用枚举(Enum)来代替int常量
第30条:用枚举(Enum)来代替int常量枚举类型(enum type)是指由一组固定的常量组成合法值的类型 ,例如一年中的季节、太阳系中的行星或者一副牌中的花色。在编程语言还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具名的 int 常量,每个类型成员一个常量:public static final int APPLE_FUJI = 0;public static final...原创 2019-06-10 18:45:08 · 273 阅读 · 0 评论 -
跟我学(Effective Java 2)第31条:用实例域代替序数
第31条:用实例域代替序数许多枚举天生就与一个单独的 int 值相关联。所有的枚举都有一个 ordinal 方法,它返回每个枚举常量在类型中的数字位置。你可以试着从序数中得到关联的 int 值:public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET,SEXTET, SEPTET, OCTET, NONET, DECT...原创 2019-06-10 18:51:58 · 145 阅读 · 0 评论 -
跟我学(Effective Java 2)第32条:用EnumSet代替位域
第32条:用EnumSet代替位域如果一个枚举类型的元素主要用在集合中,一般使用int枚举模式,将2的不同倍数赋予每个常量:public class Text { public static final int STYLE_BOLD = 1 << 0; public static final int STYLE_ITALIC = 1 << 1; ...原创 2019-06-10 19:03:08 · 222 阅读 · 1 评论 -
跟我学(Effective Java 2)第69条:并发工具优先于wait和notify
第69条:并发工具优先于wait和notifyJava 1.5 版本发行之后,Java平台就提供了更高级的并发工具,wait和notify的组合就不主要了。既然正确的使用wait和notify比较困难,就应该用更高级的并发工具来代替。java.util.concurrent包中更高级的工具分成三类:Executor Framework、并发集合(Concurrent Collection)以及同...原创 2019-06-20 17:32:57 · 454 阅读 · 0 评论 -
跟我学(Effective Java 2)第70条:线程安全性的文档化
第70条:线程安全性的文档化在一个方法声明中出现synchronized修饰符,这是个实现细节,并不是导出的API的一部分。它并不一定表明这个方法是线程安全的。线程安全性有多种级别。一个类为了可被多个线程安全的使用,必须在文档中清楚地说明他所支持的线程安全性级别。1 不可变的(immutable)——这个类的实例是不变的。所以,不需要外部的同步。 这样的例子包括String、Long和Big...原创 2019-06-20 17:39:24 · 198 阅读 · 0 评论 -
跟我学(Effective Java 2)第35条:注解优先于命名模式
第35条:注解优先于命名模式Java 1.5之前,一般使用命名模式表明有些程序元素需要通过某种工具或者框架进行特殊处理。例如,JUnit测试框架原本要求用户一定要用test作为测试方法名称的开头。命名模式的缺点:1.文字拼写错误导致失败,测试方法没有执行,也没有报错。2.无法确保它们只用于相应的程序元素上,如希望一个类的所有方法被测试,把类命名为test开头,但JUnit不支持类级的测试,...原创 2019-06-11 18:18:13 · 173 阅读 · 0 评论 -
跟我学(Effective Java 2)第36条:坚持使用Override注解
第36条:坚持使用Override注解@Override注解,这个注解只能用于方法中声明,它表示被注解的方法声明覆盖了超类型中的同名方法的一个声明。如果坚持使用,可以防止一大类的非法错误。下面举例:public class Bigram { private final char first; private final char second; public Big...原创 2019-06-11 18:33:22 · 143 阅读 · 0 评论 -
跟我学(Effective Java 2)第76条:保护性地编写readObject方法
第76条:保护性地编写readObject方法当一个对象被反序列化的时候,对于客户端不应该拥有的对象引用,如果哪个域包含了这样的对象引用,就必须要做保护性拷贝,这是非常重要的。因此,对于每个可序列化的不可变类,如果它包含了私有的可变组件,那么在它的readObject方法中,必须要对这些组件进行保护性拷贝。有一个简单的"石蕊"测试,可以用来确定默认的readObject方法是否可以接受。测试...原创 2019-06-21 18:08:39 · 262 阅读 · 0 评论 -
跟我学(Effective Java 2)第77条:对于实例控制,枚举类型优先于readResolve
第77条:对于实例控制,枚举类型优先于readResolve在第3条中提到的,如果这个类的声明中加上了"implements Serializable"的字样,它就不再是一个Singleton。无论该类使用了默认的序列化形式,还是自定义的序列化形式(见第75条),都没有关系;也跟它是否提供了显式的readObject方法(见第76条)无关。任何一个readObject方法,不管是显式的还是默认...原创 2019-06-21 18:12:53 · 280 阅读 · 0 评论 -
跟我学(Effective Java 2)第78条:考虑用序列化代理代替序列化实例
第78条:考虑用序列化代理代替序列化实例正如第74条中提到以及本章中所讨论的,决定实现Serializable,会增加出错和出现安全问题的可能性,因为它导致实例要利用语言之外的机制来创建,而不是用普通的构造器。然而,有一种方法可以极大地减少这些风险。这种方法就是序列化代理模式(serialization proxy pattern)。序列化代理模式相当简单。首先,为可序列化的类设计一个私有的静...原创 2019-06-21 18:22:50 · 210 阅读 · 0 评论 -
跟我学(Effective Java 2)第59条:避免不必要地使用受检的异常
第59条:避免不必要地使用受检的异常受检的异常是Java设计语言的一项很好的特性。与返回代码不同,他们强迫程序员处理异常的条件,大大增强了可靠性。也就是说,过分使用受检的异常会使API使用起来非常不方便。如果方法抛出一个或者多个受检的异常,或者他必须声明他抛出这些异常,并让他们传播出去。无论哪种方法,都给程序员增添了不可忽视的负担。如果正确的使用API并不能组织这种异常条件的产生,并且一点产生...原创 2019-06-18 17:39:14 · 205 阅读 · 0 评论 -
跟我学(Effective Java 2)第60条:优先使用标准的异常
第60条:优先使用标准的异常高手可以高度的重用,异常也不例外。java平台提供了一系列基本的未受检的异常,满足了绝大多数API的异常抛出需求。重用现有异常有很多好处。其中最主要的好处是,他使你的API更加易于学习和使用,因为他与程序员已经熟悉的习惯用法是一致的。第二个好处是,对于用到这些API的程序而言,他们的可读性会更好,因为他们不会出现很多程序员不熟悉的异常。最后(也是最不重要的)一点是,...原创 2019-06-18 17:41:24 · 181 阅读 · 0 评论 -
跟我学(Effective Java 2)第61条:抛出与抽象相对应的异常
第61条:抛出与抽象相对应的异常如果方法抛出的异常与它所执行的任务没有明显的联系,这种情形物会使人不知所措。当方法传递由低层抽象抛出的异常时,往往会发生这种情况。除了使人感到困惑之外,这也让实现细节污染了更高层的API。如果高层的实现在后续的发行版本中发生了变化,它所抛出的异常也可能会跟着发生变化,从而潜在地破坏现有的客户端程序。为了避免这个问题,更高层的实现应该捕获低层的异常,同时抛出可以按...原创 2019-06-18 17:48:16 · 333 阅读 · 0 评论 -
跟我学(Effective Java 2)第62条:每个方法抛出的异常都要有文档
第62条:每个方法抛出的异常都要有文档描述一个方法所抛出的异常,是正确使用这个方法时所需文档的重要组成部分。因此,花点时间仔细的为每个方法抛出的异常建立文档是特别重要的。始终要单独的声明受检的异常,并且利用Javadoc的@throws标记,准确的记录下抛出每个异常的条件。如果一个方法可能抛出多个异常类,则不要使用“快捷方式”声明他会抛出这些异常类的某个超类。这样的声明不仅没有为程序员提供关于...原创 2019-06-18 17:52:22 · 173 阅读 · 0 评论 -
跟我学(Effective Java 2)第75条:考虑使用自定义的序列化形式
第75条:考虑使用自定义的序列化形式如果这个类实现了Serializable接口,并且使用了默认的序列化形式,你就永远无法彻底摆脱那个应该丢弃的实现了。它将永远牵制住这个类的序列化形式。如果没有先认真考虑默认的序列化形式是否适合,则不要贸然接受。一般来将,只有当你自行设计的自定义序列化形式与默认的序列化形式基本相同时,才能接受默认序列化形式。默认的序列化形式描述了改对象内部所包含的数据,以及...原创 2019-06-21 18:00:07 · 242 阅读 · 0 评论 -
跟我学(Effective Java 2)第37条:用标记接口定义类型
第37条:用标记接口定义类型***标记接口(marker interface)是没有包含方法声明的接口,而只是指明一个类实现了具有某种属性的接口。***例如,Serializable接口。标记接口有两点胜过标记注解。首先,也是最重要的一点是,标记接口定义的类型是由被标记类的实例实现的;标记注解则没有定义这样的类型。 这个类型允许你在编译时捕捉在使用标记注解的情况下要到运行时才能捕捉到的错误。...原创 2019-06-11 18:46:22 · 177 阅读 · 0 评论 -
跟我学(Effective Java 2)第54条:谨慎地使用本地方法
第54条:谨慎地使用本地方法JNI (java native interface) 允许java 应用程序调用本地方法(native method)。本地方法:本地程序设计语言编写的特殊方法(比如C 或C++ 代码),并返回到java设计语言。本地方法主要提供三种用途:1 访问“特定于平台的能力”的机制,比如 注册表、文件锁。2 访问遗留代码库的能力,可以访问遗留数据。3 可以通过本地...原创 2019-06-17 17:18:06 · 777 阅读 · 0 评论 -
跟我学(Effective Java 2)第55条:谨慎地进行优化
第55条:谨慎地进行优化优化的弊大于利,特别是不成熟的优化。在优化过程中,产生的软件可能既不快速,也不正确,而且还不容易修正。不要因为性能而牺牲合理的结构。要努力编写好的程序而不足快的栏序。如果好的程序不够快,它的结构将使它可以得到优化。好的程序体现了信息隐藏 (information hiding)的原则:只要有可能,它们就会把设计决策集中在单个模块中,因此,可以改变单个决策,而不会影响到系...原创 2019-06-17 17:23:40 · 165 阅读 · 0 评论 -
跟我学(Effective Java 2)第74条:谨慎地实现Serializable接口
第74条:谨慎地实现Serializable接口序列化(object serialization)API,它提供了一个框架,用来将对象编码成字节流,以及从字节流编码中重新构建对象。“将一个对象编码成一个字节流”,这就称作序列化(serializing)该对象;相反的处理过程被称作反序列化(deserializing)。要想使一个类的实例可被序列化,非常简单,只要在它的声明中加入"impleme...原创 2019-06-21 17:16:40 · 291 阅读 · 0 评论 -
跟我学(Effective Java 2)第56条:遵守普遍接受的命名惯例
第56条:遵守普遍接受的命名惯例不严格的讲,这些命名惯例分为两大类:字面的和语法的。字面的命名惯例比较少,但也涉及包,类,方法,域和类型变量。包的名称应该是层次状的,用句号分隔每个部分。 任何将在你的组织之外使用的包,其名称都应该以你的组织的Internet域名开头,并且将顶级域名放在前面,例如edu.cmu , com.sun ,gov.nsa。标准类库和一些可选的包,其名称以java和j...原创 2019-06-17 17:32:27 · 140 阅读 · 0 评论 -
跟我学(Effective Java 2)第57条:只针对异常的情况才使用异常
第57条:只针对异常的情况才使用异常 try { int i = 0; while (true){ range[i++].climb(); } }catch (ArrayIndexOutOfBoundsException e){ }这段代码明显是想让数组一...原创 2019-06-17 17:42:53 · 193 阅读 · 0 评论 -
跟我学(Effective Java 2)第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常
第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常java 程序设计语言可抛出三种结构(Throwable):受检异常(Checked Excepction)、运行时异常(RunTimeException)、错误(Error)。在决定使用受检的异常或是或受检的异常时,主要的原则是:如果期望调用者能够适当恢复,对于这种情况就应该使用受检的异常。通过抛出受检的异常,强迫调用者在一个ca...原创 2019-06-17 17:51:09 · 595 阅读 · 0 评论 -
跟我学(Effective Java 2)第67条:避免过度同步
第67条:避免过度同步ps:此条本人依然在理解中。依据情况的不同,过度同步可能会导致性能降低、死锁,甚至不确定的行为。为了避免活性失败和安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制。换句话说,在一个被同步的区域内部,不要调用设计成要被覆盖的方法,或者是由客户端以函数对象的形式提供的方法。从包含该同步区域的角度来看,这样的方法是外来的(alien)。这个类不知道该方法...原创 2019-06-19 18:36:58 · 205 阅读 · 0 评论 -
跟我学(Effective Java 2)第66条:同步访问共享的可变数据
第66条:同步访问共享的可变数据关键字synchronized可以保证同一时刻,只有一个线程可以执行某个方法,或者摸一个代码块。许多人把同步的概念理解为一种互斥的方式,即,当一个对象被一个线程修改的时候,可以阻止另一个线程观察到对象内部不一致的状态。这种观点对象创建的时候处于一致的状态,当有方法访问它的时候,它就被锁定了。这种观点是正确的,但是它并不是同步的全部意义。同步不仅可以阻止一个线程看...原创 2019-06-19 18:07:35 · 177 阅读 · 0 评论 -
跟我学(Effective Java 2)第65条:不要忽略异常
第65条:不要忽略异常尽管这条建议看上去是显而易见的,但是它却常常被违反,因而值得再次提出来,当API的设计者声明一个方法将抛出某个异常的时候,他们等于正在试图说明某些事情。所以,请不要忽略它!要忽略一个异常非常容易,只需将方法调用通过try语句包围起来,并包含一个空的catch块。空的catch块会使异常达不到应有的目的,即强迫你处理导常的情况。忽略异常就如同忽略火警信号一样——若把火警信号...原创 2019-06-19 17:35:54 · 177 阅读 · 0 评论 -
跟我学(Effective Java 2)第7条:避免使用终结方法
第7条:避免使用终结方法终结方法(finalize)通常是不可预测的,也是很危险的,一般情况下也是不必要的。使用终结方法会导致行为不稳定、降低性能,以及可移植性的问题。虽然终结方法也有可用之处,但是还是应该避免使用它。终结方法的坏处:及时的执行终结方法正是垃圾回收算法的主要功能,不同的JVM在执行终结方法的时候的表现大相径庭,如果程序依赖于终结方法被执行的时间点,那么这个程序的行为在不同的J...原创 2019-05-31 18:48:37 · 171 阅读 · 0 评论