您的位置:首页 > Web前端

Effective Java(避免使用最终方法、覆盖equals时请遵守通用约定)

2017-09-20 13:42 483 查看
避免使用最终方法

对于Java来说垃圾回收是自动的,或者称之为不可预知或不可控,尽管finalize方法所代表的也是在垃圾回收前所做的一些动作,但对于GC的时间你不能掌握,也就是说不能保证finalize方法会被及时执行,这是很危险的,一般情况下这个方法不会被用到。

终结方法的两点用途:

第一种用途就是充当一个“安全网”,终结方法“本该”是在GC前做一些清理动作,但GC的时间未知,也就是终结方法执行时间未知,对于FileInputStream类我们都知道应该在try-finally中对其调用close方法,但也许我们会忘记编写此方法,在FileInputStream源代码中就实现了终结方法目的就在于如果忘记了close方法,至少还有终结方法,虽然可能不能得到及时执行,但晚执行总比不执行好吧。

第二个用途可能使用的场景就可能比较少,JVM只回收普通对象,对于本地对象(也就是不是Java实现的对象),JVM并不会对它进行回收,此时我们就可以在终结方法中对本地对象进行一些清理操作,但一定记住一定要是“不拥有关键资源的前提”,且在子类中重写了终结方法一定要现实调用super.finalize(),否则父类的终结方法不会被调用。

覆盖equals时请遵守通用约定

 对于equals方法,在编码中最常用的可能就是比较两个字符串是否是值相等的。需要自己重写equals方法的场景可能并不是人人都能有幸碰到,而如果碰到了该怎么办,本条目下书中说明了重写equals方法时需要遵守的一些通用约定,如果不遵守这些约定可能导致无法和其他类配合使用。

  equals方法来自于Object类:

        public boolean equals(Object obj){

               return(this == obj)

        }

 顶级类只提供了引用是否相等,如果你需要自己实现一个逻辑是否相等,此时则需要重写equals方法,例如String类,但当在重写equals方法时,应该遵守以下约定:

  1、自反性:对于任何非null的引用值x,x.equals(x)必须返回true。也就是说一个类的实例一定是与它本身相等的,不管你怎么实现它的逻辑判断,但它的“本”不能忘。

  2、对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。这条比较好理解,x=1,y=1,你不能y=x而x!=y吧。

  3、传递性:对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。显而易见。

  4、一致性:对于任何非null的引用值x和y,只要equals的比较操作在对象中的所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致地返回false。这条显然,你不能多调用判断几次它的结果就产生变化了吧。

  对于任何非null的引用值x,x.equals(null)必须返回null。

  一定要反复检查测试自己重写的equals方法是否遵守以上约定,否则程序可能会变得不正常,因为许多类,包括所有的集合类都依赖于是否遵守了equals约定。书中举了详细的例子来说明上述约定,这里不再叙述。

  我们来分析下String类中重写的equals方法:

       //String.equals

       public boolean equals(Object anObject) {

           if (this == anObject) {    //是否等于自身

                return true;

           }

          if (anObject instanceof String) {    //类型是否相等

             String anotherString = (String) anObject;    //转换类型

             int n = value.length;    

             if (n == anotherString.value.length) {    //先判断长度是否相等

                    char v1[] = value;

                    char v2[] = anotherString.value;

                    int i = 0;

                    while (n-- != 0) {    //一个一个字符判断值是否相等

                        if (v1[i] != v2[i])

                                return false;

                          i++;

                      }

                        return true;

                }

           }

             return false;

        }

String中equals方法的实现实际上就是书中给我们的重写equals的一些诀窍:

  1、使用==操作检查“对象是否为这个对象的引用”,这不是必须的,只是作为一种性能优化,例如Integer类中并无此项判断。

  2、使用instanceof操作符检查“参数是否为正确的类型”。

  3、把参数转换成正确的类型。

  4、对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域想匹配。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐