effective java 第二天

7.避免使用终结方法

一个对象从变得不可到达开始,到他的终结方法被执行,所花费的这段时间是任意长的。所以在不同的JVM上,程序运行的表现可能会截然不同。

不应该依赖终结方法来更新重要的持久状态。

Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它会被执行。不要被System.gc()方法和System.runFinalization()两个方法所诱惑,因为他们确实增加了终结方法被执行的机会,但是他们并不保证终结方法一定会被执行。

如果确实有资源需要被终止,可以显示地提供一个终止方法(比如InputStream、OutputStream方法里面的close()方法,Timer里面的cancel()方法等);

显示的种植方法经常和try-catch-finally结构结合起来使用。

8.覆盖equals时请遵守通用约定

不希望equals方法被覆盖的情形:

应该覆盖Object.equals的情形:类自己具有“逻辑相等”的概念,而且父类还没有覆盖equals实现期望的行为。

equals的性质:

扫描二维码关注公众号,回复: 3528984 查看本文章

equals方法编写的技巧:

因为这并没有重写Object中的equals方法,而是仅仅把它重载了。

9.覆盖equals时总要覆盖hashCode

哈希码相同的对象被放在同一个散列桶里面(bucket)。

生成哈希码是有一定技巧的。

对于某些不可变的、计算散列码开销较大的类,可以用lazily initialize()延迟初始化:将哈希码第一次调用时,才初始化。

但是这并不能产生最新的散列码。

10.始终要覆盖toString()方法

默认的toString方法返回:   类型名@16进制哈希码。

重写的toString方法应该返回对象包含的信息,如果对象太大,则返回信息摘要。

11.谨慎地覆盖clone

cloneable接口并没有包含任何方法,他只是决定了Object中受保护的clone方法实现的行为:如果一个类实现了cloneable,那么clone方法会返回该对象的逐域拷贝,否则会抛出异常。

比较重要的问题就是深拷贝和浅拷贝:

https://www.cnblogs.com/acode/p/6306887.html

浅拷贝:调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内 容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对 象中相应的变量指向的是同一个对象。 这就是所谓的“影子”克隆。

为什么调用super.clone():

实现了Cloneable接口,这是一个标记,证明这个类可以被克隆,并可以调用Object的clone方法,而super.clone()正是克隆当前对象,这里的super.指的是调用父类的clone方法,实现浅克隆,即只clone当前对象而不clone当前对象的子对象。至于clone方法的实现,具体没了解过,只知道利用反射机制实现的,可以完全复制当前对象,但是由于返回值是Object,所以需要强转类型

在深拷贝的时候,引用的成员也要实现Cloneable接口,并复写clone()方法。

12.考虑实现Comparable接口(用于排序)

实现Comparable接口的类可以这样排序:Arrays.sort()或者Collections.sort()

public interface Comparable<T>{

      int compareTo(T t)

}

13.使类和成员的可访问性最小

规则一:尽可能地使每个类或者成员不被外界访问

对于顶层的类或接口:package-private  or   public(如果能做成包私有的就做成包私有,如果一个包私有的顶层类只是在一个类内部用到,考虑内部类)。ps  顶层类:它不是任一个类的内部类。

子类方法的访问级别不能低于被复写的父类方法的访问级别;接口里面的方法默认是public级别。

实例域绝对不能是公有的。就算是final的域,如果成为了公有的,那么就失去了对他的管控能力,因为虽然引用不能修改,但是那个对象还是可以被修改的。例外情况:静态域可以暴露出来作为常量,通常用全大写来表示(那么是基本类型,要么是不可变的对象)

14.在共有类中使用访问方法而非公有类

用getter和setter方法。

15.使可变性最小化

为了使类变成不可变,要遵循下面五条规则:

1.不要提供任何会修改对象状态的方法:没有设置方法。

2.保证类不会被扩展:把类声明成final。

3.使所有的域都是final:

4.使所有类的成为私有的:

不可变对象本质上是线程安全的,因为它不要求同步。

唯一真正的缺点是,对于每个不同的值都需要一个单独的对象。

当不可变类遇到Serializable接口时,要显示提供readResolver方法。

猜你喜欢

转载自blog.csdn.net/weixin_38967434/article/details/82736818