优势:html
印象比较深入的是:以前写安卓用到了OkHttp,使用的OkHttp是用Kotlin写的,其中实例化对象用的就是这个建造者模式,当时觉得是Kotlin链式调用的某种语法特性,后来才知道是设计模式java
主要用于多参数时,避免重叠构造器和避免无参构造器建立对象依次set参数过程当中JavaBean可能处于的不一致状态git
Singleton常见实现方法:github
经过放射调用私有构造器,能够修改构造器,建立第二个实例时抛出异常
序列化时除了实现 Serializable接口,还须要提供readResolve,防止反序列化建立新的实例设计模式
SOLID 原则中的 D 依赖反转原则 (Dependency Inversion Principle),依赖注入是该原则的一种实现方式
建立一个新的实例时,就将该资源传到构造器中数组
终结方法 (finalizer) 和 清除方法(cleaner JDK9) 都不可预测且会形成性能损失
注重时间的任务不该该使用这两种方法来完成
不该该依赖这两种方法来更新重要的持久状态(好比:释放共享资源,可能还没开始释放资源,系统就垮掉了)
TODO p25 终结方法攻击(finalizer attack)
TODO 合理用途:缓存
实现了AutoCloseable 接口安全
不用覆盖的状况(知足其一便可)架构
覆盖equals的通用规范ide
子类与父类 自反性和传递性的对立:没法再拓张可实例化的类的同时,既增长新的值组件,同时又保留equals约定
IDEA 默认子类equals写法就是:使用getClass() 比较对象,而后调用父类equals最后对比子类拓展的属性
Stream 初始化Set:
private static final Set<Point> unitCircle = Stream.of( new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(0, -1) ).collect(Collectors.toCollection(HashSet::new));
辨析:instanceof getClass()==
使用复合优于继承:提供私有Point域以及共有视图(view)方法
JDK反例:public class Timestamp extends java.util.Date,在同一个集合中使用或者其余方式混合使用,可能有不正确的行为
instanceof 第一个操做符为null 那么返回的必定为false,使用instanceof能够省略null判断
一致性,不要使equals方法依赖于不可靠的资源,JDK反例:URL equals
高质量equals诀窍
注意点:
Object的hashCode方法为native方法:public native int hashCode();
hashCode注释提到:hashCode返回的是由对象存储地址转化获得的值
As much as is reasonably practical, the hashCode method defined by class {@code Object} does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
若是没有覆盖hashCode致使两个相同实例具备不一样散列码,HashMap有一项优化,能够将每一个项相关联的散列码缓存起来,若是散列码不匹配,不会校验对象相等性
好的散列函数倾向于“为不相等的对象产生不相等的散列码”,每一个对象都被映射到同一个散列桶中,会实其退化为链表
简单解决方法:
使用31缘由:
计算机在进行数值运算的时候,是经过补码表示每一个数值的 正数原反补相同;负数反码符号位不变,其它位都取反;负数的补码在反码的基础上加1 Java 三种位运算(补码) << 左移:丢弃最高位,0补最低位 >> 右移:符号位不变,左边填充符号位 >>> 无符号右移:忽略了符号位,左边填充0
Objects类:public static int hash(Object... values) 便捷,可是相对速度慢一些:可变参数引起数组建立,基本类型须要拆箱装箱
不可变类用使用private 变量 缓存hash值, 延迟初始化(lazily initialize)
构造器为:PhoneNumber(short areaCode, short prefix, short lineNum) ,必须强转 (short)1
直接传入整数,否者报错,没有int类型构造器
注意:
Object实现:类名称@散列码无符号十六进制表示
toString 返回对象中包含的全部值得关注的信息
能够在文档中指定返回的格式,并配套静态工厂或者构造器,便于相互转换,JDK例子:BigInteger、BigDecimal、包装类
静态工具类和大多数枚举类编写toString意义不大
记得实现Cloneable接口(空的interface),否者抛出异常:java.lang.CloneNotSupportedException
Object中的clone方法:protected native Object clone() throws CloneNotSupportedException;
TODO p46
实现Cloneable接口的类是为了提供一个功能适当复杂的公有clone方法,它无需调用构造器就能够建立对象
不变类永远都不该该提供clone方法
Clone方法就是另外一个构造器;必须保证它不会伤害到原始对象,并确保正确地建立被克隆对象中的约束条件
若是域是final修饰,clone是禁止给final域赋值,Cloneable架构于引用可变对象的final域的正经常使用法是不相兼容的
线程安全:Object类 clone 没有同步
实现了Cloneable接口的类
拷贝对象更好的方法是提供拷贝构造器和拷贝工厂
最佳实践:用clone复制数组
Comparable接口:public int compareTo(T o);
将这个对象与指定对象比较,大于、等于、小于指定对象返回负整数、零和正整数,类型不匹配抛出RuntimeException:ClassCastException
通用约定
依赖比较关系的类有:TreeSet TreeMap Collections Arrays
与equals相同:没法在用新的值组件拓展课实例化的类时,同时保持compareTo约定,除非放弃面向对象抽象优点;能够经过组合方式实现Comparable接口的类增长值组件(提供“视图” view方法)
BigDecimal d1 = new BigDecimal("1.0"); BigDecimal d2 = new BigDecimal("1.00"); System.out.println(d1.equals(d2)); // false System.out.println(d1.compareTo(d2)); // 0 Set<BigDecimal> bigDecimals = new HashSet<>(); // equals 比较 bigDecimals.add(d1); bigDecimals.add(d2); System.out.println(bigDecimals); // [1.0, 1.00] Set<BigDecimal> treeSets = new TreeSet<>(); // compareTo 比较 treeSets.add(d1); treeSets.add(d2); System.out.println(treeSets); // [1.0]
注意Double和Float 使用compare比较而非 < >
Java7 提供了包装类的静态compare方法,建议在compareTo中使用
从关键域开始逐步比较全部域,某个域产生非零结果当即返回
Java 8 提供了Comparator接口,简洁,可是要付出性能成本
private static final Comparator<PhoneNumber> COMPARATOR = comparingInt((PhoneNumber pn) -> pn.areaCode) .thenComparingInt((PhoneNumber pn) -> pn.prefix) .thenComparingInt((PhoneNumber pn) -> pn.lineNum); @Override public int compareTo(PhoneNumber pn) { return COMPARATOR.compare(this, pn); }
GitHub effective-java-3e-source-code
Effective Java - 豆瓣
java中instanceof和getClass()的做用
Initializing HashSet at the Time of Construction
Java Object.hashCode()源码分析
通俗易懂的 Java 位操做运算讲解
Java 位运算(移位、位与、或、异或、非)