equalsignorecase

本博客主要阐述
1。不需要覆盖的场景等于
2。需要覆盖的场景等于
3。对五个常见约定的理解
4。实现高质量的秘诀等于
5。注释1。不需要。

2.我不在乎类是否提供“逻辑相等”的测试函数[br/]书中的例子是ja.util.Random covers equals检查两个随机实例是否产生相同的随机数序列,但设计者并不认为客户需要或期望这样的函数。在这种情况下,从Object继承的equals实现就足够了。

3.父类已经覆盖了equals,从父类继承的行为也适用于子类
比如大部分Set实现都是从AbstractSet继承equals。

4.如果该类是私有的或者在包级别是私有的,那么可以肯定它的equals方法永远不会被调用。在这种情况下,无疑应该覆盖equals方法,以防止它在
之外被调用。在这种情况下,只是放弃了equals,并没有新的功能。

@ override
public boolean equals(Object obj){
throw new assertion error();
}
2。需要重写equals的场景
如果类有自己独特的“逻辑相等”概念(不同于对象相等的概念),而父类还没有重写equals来实现预期的行为,那么equals方法就需要被重写。当重写equals方法时,必须遵守以下一般约定。

反身:对于任何非空引用值x,x.equals(x)必须返回true
对称:对于任何非空引用值x和y,当且仅当y.equals(x)返回true,X.equals(y) null返回true
传递:对于任何非空引用值x,y和z,如果X.equals(y)返回true,y.equals(z)返回true,则x.equals(z)必须返回true
一致性:对于任何非空引用值x和或者统一返回false
Non-nullity:对于任何非空的引用值x,x.equals(null)必须返回false
III。了解五个常见的约定
1。反身性
这个。

2.对称性
任何两个物体在是否相等的问题上一定是一致的。比如下面不一致,违反对称性。NotSring类中的equals方法忽略大小写,只要值相等就返回true。但是,String类中的equals不会忽略大小写。即使String类本身已经重写了equals,只要值相等就会返回true,但这只是用相同的大小写做出不同值的一种方式,所以s.equals(ns)返回false。

not string . Ja
包com.linjie

/**

@author LinJie@Description:这是一个非String类,作为待会与String类的一个比较
*/
public class NotString {
private final String s;public NotString(String s) {
if(s==null)
throw new NullPointerException();
this.s=s;
}@Override
public boolean equals(Object obj) {
//如果equals中的实参是属于NotString,只要NotString的成员变量s的值与obj的值相等即返回true(不考虑大小写)
if(obj instanceof NotString)
return s.equalsIgnoreCase(((NotString) obj).s);
//如果equals中的实参是属于String,只要NotString的成员变量s的值与obj的值相等即返回true(不考虑大小写)
if(obj instanceof String)
return s.equalsIgnoreCase((String) obj);
return false;
}
}
测试类
package com.linjie;

导入org . JUnit . test;

public class equals Test {
@ Test
public void Test(){
not string ns = new not string(“林杰”);
String s = “林杰”;
system . out . println(” not string as object,string as parameter “);
system . out . println(ns . equals(s));
system . out . println(” String作为对象,NotString作为参数”);
system . out . println(s . equals(ns));
}
}
个结果

equalsignorecase

3。传递性
如果一个对象等于第二个对象,第二个对象等于第三个对象,那么第一个对象一定等于第三个对象。但有时会违背这一点。比如下面这个点和它的子类ColorPoint,在子类中增加一个新的颜色特性,就很容易违背这个约定。

点类
包com . linjie . a;

/**

@author LinJie@Description:是两个整数型的父类
*/
public class Point {
private final int x;
private final int y;public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}@Override
public boolean equals(Object obj) {
if(!(obj instanceof Point))
return false;
else {
Point p = (Point)obj;
return p.xx&&p.yy;
}
}
}
ColorPoint类
package com.linjie.a;

/**

@author LinJie@Description:在父类Point基础上添加了颜色信息
*/
public class ColorPoint extends Point {
private final String color;public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}//违背对称性
@Override
public boolean equals(Object obj) {
if(!(obj instanceof ColorPoint))
return false;
else
return super.equals(obj)&&((ColorPoint)obj).color==color;
}
}
测试类
package com.linjie.a;

导入org . JUnit . test;

public class equals Test 2 {
@ Test
public void Test(){
Point p = new Point(1,2);
ColorPoint CP = new ColorPoint(1,2,“红色”);
ColorPoint cp2 = new ColorPoint(1,2,“蓝色”);
system.out.println (“P是对象,cp是参数”);
system . out . println(p . equals(CP));
system.out.println (“CP是对象,P是参数”);
system . out . println(CP . equals);
}
}
个结果

从结果可以明显看出,前者忽略了颜色信息,所以为真,而后者总是为假,因为参数类型不正确。导致对称性的破坏。

另一种方法是确保对称性,但这违反了传递性,并修改ColorPoint类。

包com . linjie . a;

/**

@author LinJie@Description:在父类Point基础上添加了颜色信息
*/
public class ColorPoint extends Point {
private final String color;public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}//违反了传递性
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Point))
return false;
if(!(obj instanceof ColorPoint))
return obj.equals(this);//反转成Point的equals,忽略了颜色信息
return super.equals(obj)&&((ColorPoint)obj).color==color;
}
}
测试类
package com.linjie.a;

导入org . JUnit . test;

public class equals Test 2 {
@ Test
public void Test(){
Point p = new Point(1,2);
ColorPoint CP = new ColorPoint(1,2,“红色”);
ColorPoint cp2 = new ColorPoint(1,2,“蓝色”);
system.out.println (“P是对象,cp是参数”);
system . out . println(p . equals(CP));
system.out.println (“CP是对象,P是参数”);
system . out . println(CP . equals);
system.out.println (“CP是对象,cp2是参数”);
system . out . println(CP . equals(cp2));
}
}
结果
如果没有第三方cp2,就是正确的。

但是用cp2,违背传递性是很明显的。

显然,可以看出传递性又不好了

我们不能在扩展可实例化类的同时添加新的值组件,同时保持等号约定,除非我们愿意放弃面向对象的优势,即组合优先于继承,但本博客不会对此进行详细阐述。

4.一致性
如果两个对象相等,除非其中一个(或两个)被修改,否则它们必须保持相等。

5.非线性[/k0/]
意味着所有对象都不能为空。

@ override
public boolean equals(Object obj){
if(obj = = null)
返回false

}
以上if测试是不必要的。为了测试其参数的相等性,equals方法必须首先将参数转换为适当的类型,以便它可以调用其方法或成员变量。在转换之前,equals必须使用instanceof运算符来检查其参数是该类的对象还是子类的对象。

mytype . Ja
包com . linjie . aa;

/**

@author LinJie

*/
公共类MyType {
私有最终字符串s;

public MyType(String s){ super();this.s = s}@Overridepublic布尔等于(Object obj) { if(!(obj instanceof MyType))返回false//只要判断obj属于MyType对象或者子类对象,就可以转换成MyType类型调用其私有成员变量MyType mt =(MyType)obj;return mt.s = = s}}
测试类
包com . linjie . aa;

导入Ja . awt . color;

导入org . JUnit . test;

public class equals Test 222 {
@ Test
public void Test(){
MyType mt = new MyType(“林杰”);
system . out . println(mt . equals(null));
}
}
个结果

如果省略了instanceof检查,并且传递给equals方法的参数类型错误,那么equals方法将抛出一个ClassCastException异常,这违反了等式约定。但是,如果instanceof的第一个操作数为null,则instanceof运算符指定无论第二个操作数的类型如何都应返回false,因此不需要单独的null检查,而应使用instanceof。

四、达到高质量的诀窍等于
1。使用运算符检查参数是否是对此对象的引用。如果是,则返回true。这是一个性能优化
if(this obj)
return true;

2.使用instanceof运算符检查参数的类型是否正确,如果不正确,则返回false。所谓正确的类型是指equals方法所在的类,或者是该类的父类或接口。

3.将参数转换为正确的类型:因为instanceof测试已经在前面的步骤中完成,所以请确保转换会成功。

4.对于这个类的每个“key”字段,检查参数中的字段是否与对象中的对应字段匹配(实际上是比较两个对象的值是否相等)。

5.在你写了equals方法之后,你应该问自己三个问题:它是对称的、传递的和一致的吗?当然,equals还必须满足另外两个约定(反身性,非[/k0/]),但这两个约定通常是自动满足的
根据上面的提示,可以构造一个相对较好的equals方法
。可以看出,下面重写的equals就是按照上面的提示写的。

包linjie.com.xxx;

公共最终类电话号码{
私人最终短区号;
私有最终短前缀;
私有最终短行号;

公共电话号码(短区号,短前缀,短线路号码){ rangeCheck(区号,999,& # 34;区号& # 34;);rangeCheck(前缀,999,& # 34;前缀& # 34;);rangeCheck(行号,9999,& # 34;行号& # 34;);this . area code =(short)area code;this.prefix =(短)前缀;this . line number =(short)line number;} private static void range check(int arg,int max,String name){ if(arg & lt;0 | | arg & gtmax)抛出新的IllegalArgumentException(name+& # 34;: "+arg);} @ override public boolean equals(object obj){//1,参数是否为该对象的引用if(obj = = this)return true;//2.使用instanceof检查(!(obj instanceof PhoneNumber))返回false//3.将参数转换为正确的类型phone number pn =(phone number)obj;//4.比较两个对象的值是否相等。返回pn。线路编号= =线路编号&&pn。前缀= =前缀&&pn。区号= =区号;}}
5。注意,你在覆盖equals的时候,要一直覆盖hashCode(见第9条,这里暂且不细说)
不要试图把equals方法做得太聪明:不要试图过度寻求各种等价关系,否则你会很容易陷入各种麻烦
不要用其他类型替换equals声明中的对象。添加@override可以避免这种错误。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论