第7条:在改写equals的时候请遵守通用约定
在改写equals方法的时候,你必须要遵守通过约定
1.自反性:对于任意的引用值x,x.equals(x)一定为true
2。对称性:对于任意的引用x和y,当且仅当y.equals(x)返回true时,x.equal(y)也一定返回true
3.传递性:对于任意的引用值x,y,z如果x.equal(y)返回为true,y.equal(z)返回true,那么x.equal(z)也一定返回为true
4.一致性:对于任意的引用值x和y,如果用于equals比较对像信息没有被修改的话,那么多次调用x.equals(y),要么一致返回true,要么一致的返回false
5.对于任意的非空引用值x,x.equal(null)一定返回false
下面是equals方法的一个处方
1.使用==操作检查实参是否为指向对象的一个引用。如果是的话则返回true
2.使用instanceof操作检查实参是否为正确的类型。如果不是的话返回false
3.把实参转化到正确的类型。
4.对于该类中每一个关键域,检查实参种的域与当前对象对应的域值是否匹配。
域的比较顺序可能影响到equals方法的性能,为了获得最佳的性能,最先进行比较的域应该是最有可能不一致的域或者是比较开销最低的域。
5.当你编写完成了equals方法之后,应该问自己三个问题,它是否是对称的,传递的,一致的
8.当你改写equals的时候,总要改写hashcode
9.不要企图让equal方法过于聪明
10.不要使equals方法依赖于不可靠的资源
11.不要将equals声明中的object对象替换成其他的类型
public boolean equals(MyClass o){}
该方法为重载而不是重写
第8条:改写equals时候总要改写hashcode
1.在一个应用程序执行期间,如果一个对象的equals方法做的比较所用到的信息没有被修改的话,那么该对象调用hashcode方法多次,它必须始终如一的返回同一个整数。
2.如果两个对象equals(Object)方法是相等的,那么调用这两个对象中任何一个对象的hashcode方法必须产生同样的整数结果。
3.如果两个对象根据equals方法是不相等的,那么调用这两个对象中任何一个对象的hashcode方法,不要求必须产生不同的整数结果,然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列的性能。
一个好的散列函数通过倾向于 为不相等的对象产生不相等的散列码
处方:
1.把某个非零常数值,比如17,保存在一个叫result的int类型的变量
2。对于对象中的每一个关键域(指equal方法中考虑的每一域),完成下面步骤
a。为该域计算int类型的散列玛
i:如果该域是boolean类型则计算(f?0:1)
ii:如果是byte,char,short或则是int类型,则计算(int)f
iii:如果是long类型,则计算(int)(f^(f>>>32))
iv:如果是flot类型,则计算Float.floatToIntBits(f)
v:如果是double类型,则计算Double.doubleToLongBits(f)得到long类型,然后按照步骤2,a,iii 对long类型计算算列
vi:如果该域是一个对象的引用,并且该类是equals方法通过递归调用equals的方式比较这个域,则同样对这个域递归调用hashcode。
vii:如果该域是一个数组,则把每个元素当做单独的域来处理。
b:按照下面的公式,把步骤a中计算得到的散列玛c组合到result中
result=37*result+c
public int hashcode(){
int result=17;
result=37*result+c1;
result=37*result+c2;
result=37*result+c3;
}
不要试图从散列计算中排除掉一个对象的关键部门以提高性能。
第9条:总要改写toString
第10条:谨慎的改写clone
cloneable接口的目的是作为对象的一个mixin接口,表明这样的对象允许克隆。不幸的是,它并没有成功的表达这个目的,其中主要的缺陷在于,它缺少一个clone方法,object的clone方法是被保护的,如果不借助于映像机制,则不能仅仅因为一个对象实现了cloneable,就可以调用clone方法。即是是映像调用也可能会失败,因为病不保证该对象一定具有可反问的clone方法。
既然cloneable并没有包含任何方法,那么它到底做了什么呢?它决定了object中受保护的clone方法的实现行为:如果一个类实现了cloneable,则object的clone方法返回该对象的逐域拷贝,否则抛出cloneNotSupportedException
为了实现cloneable接口,使它对一个类确实产生了效果,由此得到一种语言本身之外的机制,无须调用构造函数就可以创建一个对象。
clone方法的通用约定是非常弱的
一般的含义是,对于任何对象x表达式
x.clone()!=x 将会返回true
x.clone().equals(x) 将会返回true
x.clone().getClass()==x.getClass()将是返回true,但是这些都不是绝对的要求
拷贝一个对象往往会导致创建一个对象的新实例,但同时也会要求拷贝内部的数据结构,这个过程中没有调用构造函数
clone结构与指向可变对象的final域的正常用法是不兼容的
第11条:考虑实现Comparable接口
compareTo方法在Object中并没有被声明。相反,它是java.lang.Comparable接口中唯一的方法:compareTo方法允许进行简单的相等比较,也允许执行顺序比较。
如果你正在编写一个值类,它具有非常明显的内在排序关系,比如按字符表顺序,按数值顺序或者按年代顺序,那么你几乎总是应该考虑现实该接口。
Compareable规范:
将当前这个对象与指定对象进行顺序比较。当该对象小于,等于或者大于指定对象的时候,分别返回一个负整数,零或者正整数。如果由于指定对象的类型而使得无法进行比较,则抛出ClassCastException异常。
依赖于比较关系的类包括有序集合类TreeSet和TreeMap,以及工具类Collections和Arrays,他们内部包含有搜索和排序算法。
如果你想为一个实现了compareable接口的类增加一个关键特性,请不要扩展这个类,而是编写一个不相关的类,其中包含一个域,其类型是第一个类,然后提供个视图返回这个域。这样做,你既可以自由的在第二个类上实现compareTo方法,同时也允许客户在必要的时候,把第二个类的实例当做第一个类的实例来看待。
例如:考虑BigDecimal类,它的compareable方法与equals不一致。如果你创建了个hashset,并加入一个new BigDecimal("1.0") 和一个new BigDecimal("1.00")。则这个集合将包含两个元素,因为两个新加入到集合中的BigDecimal实例通过equals方法来比较是不相等。然而如果你是使用TreeSet而不是hashset,则集合中只包含一个元素,因为这两个实例是通过compareTo方法进行比较是相等的。
分享到:
相关推荐
这种动态获取信息以及动态调用对象方法的功能称为Java的反射机制。反射机制为Java的操作带来极大的灵活性,可以用来动态创建对象,调用方法,访问属性。 在Frida的上下文中,反射调用通常涉及到几个关键的Java反射...
所有jsp内置对象的方法用法,方便开发人员查找
了解并熟练使用Response对象,对于编写高效的ASP应用程序至关重要。在实际开发中,还可以结合Request对象获取用户输入,Session对象跟踪用户会话,Application对象实现全局变量等,以构建更复杂的应用场景。
而在Java中,所有对象的标识都是通过引用完成的,无论是通过变量还是数组等。 - **对象与引用的关系**:Java中,程序员只能通过引用去访问或操作对象。这意味着,即使创建了一个对象,如果没有相应的引用指向它,...
而`PUBLIC` 访问修饰符表示方法和属性在所有地方都可访问,当被继承时,其访问修饰符默认为空,意味着在继承类中同样可访问。 5. **示例与语法** 示例代码中提到了`PROGRAM MAIN`,这是程序的主入口点。`VAR Inst ...
在JavaScript中,我们可以使用`for...in`循环遍历对象的所有可枚举属性,从而获取键值和对应的值。以下是一个简单的函数`getObjectKeys`,用于获取对象的所有键: ```javascript function getObjectKeys(object) {...
给定委托实例和适当的参数集,便可以用该参数集调用此委托实例的所有方法。委托实例的一个有趣和有用的属性是它不了解或不关心它所封装的方法的类;真正重要的只是方法要与委托的类型兼容, 这使委托非常适合“匿名”...
面向对象方法学是一种重要的软件开发方法,它将现实世界中的问题和解决方案转化为计算机程序的模型。在本案例中,"基于面向对象方法学的银行储蓄系统"是一个典型的计算机科学项目,旨在模拟实际银行的储蓄服务。这个...
在VBA中,对象、方法、事件是三个核心概念,理解它们对于Excel开发至关重要。 首先,我们来详细探讨“对象”。在VBA中,一切皆为对象。对象包含了数据和操作数据的方法。例如,在Excel中,工作簿(Workbook)、工作...
`static`变量是类级别的变量,被类的所有对象共享。修改`static`变量会影响到所有对象。 ```java public class MyClass { static int count = 0; // 静态变量 public MyClass() { count++; // 每创建一个对象...
* 反射机制:通过Class对象可以获取类的所有信息,例如字段、方法、构造函数等,可以用于反射机制。 * 动态加载类:通过Class类中的forName()方法可以动态加载类,实现动态加载类的功能。 * 依赖注入:通过Class对象...
最直接的方法是通过编写SQL语句逐一删除用户的所有对象。例如,对于表、视图、存储过程等不同类型的对象,可以分别使用`DROP TABLE`、`DROP VIEW`、`DROP PROCEDURE`等命令。 示例代码: ```sql -- 删除表 DROP ...
在Java中,通过`new`关键字和类的构造方法来创建对象。实验中,我们创建了两个`Monkey`对象`monkey1`和`monkey2`,并调用了它们的方法,展示了对象的使用。 成员变量和局部变量是Java中的两种变量类型。成员变量是...
- clone() 方法是 Java 中的一个方法,它可以创建对象的拷贝,但是需要实现 Cloneable 接口,clone() 方法可以创建浅拷贝或深拷贝,浅拷贝只拷贝对象的引用,而深拷贝则拷贝对象的所有成员变量。 - 序列化机制是 ...
他也是所有对象的顶级对象,通过Window对象的子对象进行操作,可以实现更多的效果。 1、Window对象属性 每个对象都有自己的属性,顶级对象Window是所有其他子对象的父对象,它可以出现在每个页面上,并且可以咋单个...
这段代码的主要目的是通过Type Library Interface (简称 TLI) 来获取一个对象的全部信息,包括该对象支持的所有属性、事件和方法等。通过这种方式,可以动态地了解一个对象的功能,这对于编写通用性强、灵活性高的...
在面向对象软件中,测试用例应基于对象的行为进行编写,确保每个方法都能按照预期执行并产生正确的结果。 测试用例生成是面向对象测试中的关键技术。由于对象间的依赖关系和复杂交互,生成有效的测试用例是一项挑战...
在本主题中,我们将深入探讨如何在控制台中检查JavaScript对象的方法和属性,这对于理解和解决问题至关重要。 首先,理解JavaScript对象的基本概念是至关重要的。对象是键值对的集合,这些键可以是字符串或符号,而...
对于 PHP 版本低于 5.2.6 的情况,可以采用 `ReflectionClass` 类来获取一个对象的所有方法。`ReflectionClass` 是 PHP 的反射 API 中的一个重要组成部分,它提供了一种动态获取类信息的能力,包括类的方法、属性等...
对于向上转型的对象,`equals()`方法会根据重写的情况来判断,而`==`始终比较引用。 7. **匿名内部类**:即使没有显式定义子类,也可以通过匿名内部类实现子类对象赋值给父类对象的操作,这在处理接口时非常常见。 ...