`

《Effetive Java》读书笔记二

阅读更多
第二章 所有对象共有的方法
尽管Object是一个具体的类,但是它设计的主要目标是为了去扩展,所以他的所有的非final的方法
(equals, hashCode, toString, clone, and finalize)都有一个明确一般的约定。


条款8 覆写equals要遵循一般的约定:
不覆写equals的情况:
1、每一个实例本身就是唯一的(如Thread)
2、对是否提供逻辑的equals不关心(如Random没有必要取测试两个Random实例生成的随即序列是否一致

)。
3、超类已经覆写了equals,并且这个Equals对子类也适应。
4、如果类是私有的或者包私有的,那么你要确定equals将不会被调用。

如何恰当的实现equals:
1、自反省:这个不可能被违反
2、对称性:去Wapper一个类,然后增加点属性,如果试图兼容对原始类型的equals,就会违反
   因为原始类型不可能去预测和兼容对wrapper之后类的equals。
  
3、传递性:子类试图兼容对父类的equals
// Broken - violates transitivity!
@Override public boolean equals(Object o) {
	if (!(o instanceof Point))
		return false;
	// If o is a normal Point, do a color-blind comparison
	if (!(o instanceof ColorPoint))
		return o.equals(this);
	// o is a ColorPoint; do a full comparison
	return super.equals(o) && ((ColorPoint)o).color == color;
}

ColorPoint p1 = new ColorPoint(1, 2, Color.RED);
Point p2 = new Point(1, 2);
ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);
p1.equals(p2) p2.equals(p3) 但是p1.equals(p3) return false;
这样实际没有办法给一个类的子类增加一个属性,而保留equals的约定。
文中说试图使用getClass来消除继承的影响,而保证只有每个类自己的实例
之间的比较会相等,这会违反面向对象的重要法则Liskov替换法则,
书中举的这个例子感觉还是很牵强的,父类对象继承下来的equals,如果子类
没有实例字段的增加,就应该默认支持(new CounterPoint(1,0)).equals(
new new Point( 1, 0))么?我感觉未必如此。
其实使用instanceof代替getClass的在equals使用的唯一理由是:
使用getClass就无法调用super.equals来判断继承下来的字段equals了,而只能把继承下来的
字段一一比较,这点对编写代码,特别是使用第三方的代码而来说是一个很繁琐而困难的事情。
而使用getClass保证只有每个类自己的实例之间的比较才可能相等,这其实是一个好的
事情,因为我们几乎不会去判断一个子类和父类的equals关系,事实上如书所说,
无法保证equals的Contract会使得代码行为不确定而诡异。
4、一致性(例如URL使用ip来判断equals,会因为网络问题而产生不一致的问题)
不要让equals依赖与不可靠的资源
5、非null性,事实上instanceof保证了这一点。
总结:
1、首先使用==做判断能够提高比较的性能
2、使用instanceof来判断参数是否为正确的类型
3、强制转换成正确的类型。
4、对每个字段判断是否相等。
5、验证equals的对称性传递性和一致性
6、不要过度的使用equals(File)
7、使用@Override来确保equals函数签名的正确。
8、equals的对像hashcode要相同。


条款9 覆写equals一定要覆写hashcode
Object specification指出了equals的object具有相同的hashCode。
因为hashCode在HashMap、HashSet等集合中使用,它会根据hashCode来retrieve对象。

如何设计hashCode:
对每一个字段转化成整数:result = 31 * result + c;
对于不变对象考虑hashCode缓存:
int result = hashCode;
if (result == 0) {//if not cacalute.
//...
}

return result;



条款10 一直要覆写toString方法:
提供好的toString方法,会让你的代码使用起来有一种愉快的感觉。print,printf用起来会很爽。
toString方法要返回对象中所有有用的信息。
是否在文档中指定toString返回的格式,都要在文档中表明意图。
指定格式优点更清晰,缺点用户如果试图依赖于toString的返回的格式,会使得更改toString的实现困

难。让用户依赖于更少的实现,使得API的实现重新实现更容易。

条款11 明智的覆写clone方法。
Cloneable接口作为一个mixin接口,来说明一个对象允许复制,但是由于clone作为Object的一个protected方法,它可能无法去体现这一点,这是很不幸的。但可能考虑Clone方法存在一定的安全问题
才这么做的。
当成员中有Object reference的时候考虑是否要deep copy.
特别是写一个类,意图被别的类扩展的话,一定要妥善的实现Clone方法,否则别的类也无法正常clone。

条款 12 考虑实现Comparable接口
对于想按照一种自然的方式来排序对象的话,实现Comparable接口是一个明智的选择。
当然像Collections的sort提供了回调的Comparator参数,这一点对于没有实现Comparable接口或者
想在某个时候定制这种比较方法非常有效。

2
0
分享到:
评论

相关推荐

    Effetive c++ second Edition

    前言 這本書是多年來我對專業程式員所做的C++ 教學課程下的一個自然產物。我發現,大部份學生在一個星期的密集訓練之後,即可適應這個語言的基本架構,但要他們「將這些基礎架構以有效的方式組合運用」,我實在不感...

    More Effetive c++

    #### 二、C++ 编程思维模式 C++ 提供了四种不同的编程思维模式,这使得它既强大又复杂: 1. **过程化编程**(Procedural-based):侧重于函数和过程的使用,强调顺序执行。 2. **基于对象编程**(Object-based):...

    Effetive STL.doc

    2. 关联容器与排序: - 条款19区分了相等和等价的概念,这对使用set和map至关重要。 - 条款20建议为指针关联容器指定比较类型,以满足特定排序需求。 - 条款22提醒不要直接修改set或multiset的键,以免破坏排序。...

    EFFETIVE STL

    2. **容器的特性与选择**:根据不同的需求选择合适的容器至关重要。例如,vector提供动态数组的功能,适合快速随机访问;list则以链表形式存储数据,插入和删除操作高效;set基于红黑树实现,提供排序和唯一性保证。...

    学生成绩管理系统java程序设计.doc

    学生成绩管理系统_java程序设计 本文档主要介绍了学生成绩管理系统的设计和...学生成绩管理系统是一个基于 Java 语言的学生信息管理系统,旨在提供一个 effetive 和efficient 的方式来管理学生信息,提高教学效率。

    effective-go中文版

    因此,不应该简单地将C++或Java程序翻译成Go程序,而应该从Go的角度重新思考问题的解决方案。理解Go的特性和惯用法对于编写高质量的Go代码至关重要。 2. 格式化 Go语言的源代码格式化使用标准的工具`gofmt`,它能够...

    A Markov Process Based Approach to Effective Attacking JPEG Steganography

    具体来说,文中提出了一个计算每个差分JPEG二维数组转移概率矩阵的方法,以利用块内相关性;而通过计算那些差分模式二维数组的“平均”转移概率矩阵来利用块间相关性。这些矩阵中的所有元素被用作隐写分析的特征。 ...

    c# 2nd note

    ### 2. 简化属性的定义 简化属性定义的方法有多种,例如可以通过自动实现的属性来减少代码量,并且保持良好的封装性。 ```csharp public class Customer { public virtual string Name { get; set; } } ``` ### ...

    医疗卫生面试真题:卫生类典型面试题汇总及答案.pdf

    * Effective communication:面试时要善于与面试官进行 effetive communication,准确地表达自己的想法和观点。 三、医学基础知识 * 医疗卫生面试中涉及到的医学基础知识包括:人体解剖学、生理学、病理学、药理学...

    基于WEB的 教育资源管理系统设计与开发

    2. 需求分析 需求分析是指对系统的需求进行分析和定义,以确定系统的功能和性能要求。在本系统中,需求分析包括信息服务功能、用户系统、讨论区、资源中心和系统管理等几个方面的需求分析。 3. 功能模块 功能模块...

    不错的STL文档学习资料

    2. **详细解说STL string Main TWiki.mht**:字符串是STL中一个非常重要的容器,这个文件可能详细讲解了`std::string`的使用,包括构造、操作、字符串连接、查找、替换等基本操作,以及在实际编程中的一些高级用法。...

Global site tag (gtag.js) - Google Analytics