关于== 、equals和instanceof方法你想知道的一切——Java

本文部分内容参考《疯狂Java讲义》


这篇文章其实本来已经写好了的,但是由于官方的设计和本人的疏忽问题,导致被无意间覆盖了,所以今天特地重新写了一份,希望大家在写新博客的时候 如果编辑界面直接显示了上一篇编辑过的论文,那么一定要记得点击写新文章,否则在你编辑发表后会发现你刚编辑的文章已经覆盖了之前的文章,而且是根本恢复不了,所以大家在操作时一定要注意这点,避免不必要的损失。


以后贴程序直接贴图吧,这样看起来更加好看,花花绿绿的比md自带的代码块要好多了。。(话说md写得好以后在申请涨工资的时候能加分吗)


== 和equals方法

Java程序中测试两个变量是否相等有两种方式:一种是利用 == 运算符, 另一种是利用 equals()方法。当使用 == 来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),则只要两个变量的值相等,就将返回true。
  但对于两个引用变量类型,只有它们指向同一个对象时, == 才会判断并返回true, == 不可用于比较类型上没有父子关系的两个对象。下面程序是犯了使用== 来判断两种类型变量是否相等的结果。

![这里写图片描述](https://img-blog.csdn.net/20170513215911737?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjIwNzM4NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

我们在这里可能会有疑问 , “hello” 直接量和 new String(“hello”)有什么区别?
  当Java程序直接使用形如“hello”的字符串直接量(包括可以在编译时就计算出来的字符串值)时,JVM将会使用常量池来管理这些字符串;当使用 new String(“hello”)时,JVM会先使用常量池来管理"hello"直接量,再调用String类的构造器来创建一个新的string对象,新创建的string对象被保存在堆内存中。换句话说,newString(hello)一共产生了两个字符串对象。

常量池(constant pool)专门用于管理在编译时被确定并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口中的常量,还包括字符串常量。

![这里写图片描述](https://img-blog.csdn.net/20170513222618797?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjIwNzM4NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

JVM常量池保证相同的字符串直接常量只有一个,不会产生多个副本。例子中s1、 s4、s5所引用的字符串可以在编译器就确定下来,因此它们都将引用常量池中的同一个字符串对象。
  使用new string()创建的字符串对象是运行时创建出来的,它被保存在运行时内存(既堆内存),不会放入常量池中。
  
##Object类的equals()方法

所有引用变量都可以调用该方法来判断是否与其他引用变量相等。但使用这个方法判断两个对象相等的标准与使用==运算符没有区别,同样要求两个引用变量指向同一个对象才会返回true。因此这个Object类提供的equals()方法没有太大的实际意义。所以我们如果想用自定义的相等标准我们可以重写它

##String类的equals()方法

String类的equals()方法判断两个字符串相等的标准是:只要两个字符串所包含的字符序列相同,通过equals()比较将返回true。否则将返回false。

#重写equals方法
  Object默认提供的quals只是比较对象的地址,和==效果一样,所以我们在实际当中经常要重写equals方法

![这里写图片描述](https://img-blog.csdn.net/20170513225052311?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjIwNzM4NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![这里写图片描述](https://img-blog.csdn.net/20170513225102385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjIwNzM4NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

上面的程序常用写了Person类的equals方法,指定了Person对象和其他兑现相等的标准:另一个对象必须是Person类的实例,且两个Person对象的idStr相等,即可判断两个Person对象相等。在这种判断标准下,可认为只要两个Person对象的身份证字符串相等,即可判断相等。

关于《疯狂java》这本书中 给出了如下equals方法的基本满足条件

  • 自反性: 对任意x,x.equals(x)一定返回true
  • 对称性:对任意x和y,如果y.equals(x)返回true 则x.equals(y)也返回true
  • 传递性:对任意x,y,z,如果x.equals(y)返回true,y.equals(x)返回true 则x.equals(z)也一定返回true
  • 一致性:对任意x和y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true要么一直是false
  • 对任何不适inull的x ,x.equals(null)一定返回false

关于equals方法《Java核心技术》中给出如下建议:

  • 显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。
  • 检测this与otherObject是否引用同一个对象:
    • if(this == otherObject) return true;
    • 这条语句只是一个优化。实际上这是一种经常采用的形式。因为计算这个等式要比一个个的比较类中的域所付出的代价小得多。
  • 检测otherObject是否为null,如果为null,返回false。这项检测是很必要的
    • if(otherObject == null) return false
  • 比较this和otherObject是否属于同一个类。如果equals的语义在每个字累中有所改变,就使用getClass方法检测:
    • if(getClass()! = otherObject.getClass()) return false ;
    • 如果所有的子类都拥有统一的语义,就使用 instanceof检测:
    • if(!(otherObject instanceof ClassName)) return false;
  • 将otherObject转换为相应的类类型变量:
    • ClassName other = (ClassName) otherObject
  • 现在开始对所有需要比较的域进行比较了。使用== 比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true;否则返回false。
    • return field1 == other.field1   && Objects.equals(field2, other.field2)   && ...;
    • 如果在子类中重新定义equals,就要在其中包含调用super.equals(other)

intanceof运算符

对于intanceof运算符而言,当前面对象是后面类的实例或其子类的实例时都返回true,所以重写equals()方法判断两个对象是否为同一个类的实例时使用instanceof是有问题的。比如这里有个Teacher类型的变量t,如果判断 t instanceof Person, 这也将返回true ,但对于重写equals()方法的要求而言,通常要求两个对象是同一个类的实例,因此使用intanceof运算符不太合适。改为使用t.getClass() == Person.class比较合适。(参考上面代码)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值