书里说用equals来比较,但是用==也没问题啊,比较结果是一样的,请教一下有啥区别呢?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了书里说用equals来比较,但是用==也没问题啊,比较结果是一样的,请教一下有啥区别呢?相关的知识,希望对你有一定的参考价值。

==比较的是内存地址,如果你是这样

String a = "aaa";
String b = "aaa";
System.out.println(a == b);结果:true,但是你如果是这样:

String a = new String("aaa");
String b = new String("aaa");
System.out.println(a == b);结果:false
因为它分配了两个内存地址,如果用equals则结果为true,所以在比较字符串的时候还是用equals()方法比较合理。
参考技术A 给你澄清几个概念,然后再说equals,有助理解,如不感兴趣,可越过此部分。
知道什么是引用不?引用也就是引用变量,Java中的变量按照数据类型,可以分为两种,一种是基本数据类型变量,一种是引用数据类型变量:
基本数据类型变量:byte,short,char,int,long,float,double,boolean,以这8种基本数据类型声明的变量,如:int i;
基本数据类型变量:到目前为止引用数据类型包括 类,接口,数组,枚举,注解,以它们声明的变量叫做引用变量,或者引用,如:
String s1 = new String("abc");
String s2 = "abc";
引用s1里面存的是一个地址,地址什么样你不用管,就知道 通过这个地址就可以准确的找到上面这个new出来的String对象,所以我们说,引用s1指向了这个String对象。同样,s2也指向了一个String对象。

再说 == 和 equals 的区别:
s1 == s2 是true还是false?
== 比较的是引用地址,换句话说,==号两边的这两个变量所记录的地址是不是相同,用new关键字new出来的对象位于内存的堆区,"abc"是一个字符串常量,Java中字符串常量也是String类的一个对象,字符串常量被分配在内存的data segment(数据区),现在它们是两个不同的对象,s1指向new出来的这个,s2指向这个字符串常量,s1和s2指向的是不同的对象,它们的引用地址当然不同,毫无疑问表达式返回false

再说equals方法,s1.equals(s2) 是true还是false?

有些人上来就说equals方法比较的内容,其实这是不全面的,equals方法和==的区别,面试也经常考,
equals方法是父类Object所定义的方法,用来实现两个对象内容是否相等的逻辑,说equals方法要从两个方面:
1)从Object角度来说,==与equals是一样的,都是比较引用,因为Object类的equals()方法是这样定义的, public boolean equals(Object obj) return (this == obj);
方法内部的实现就是比较引用地址,用的也是==号,所以对于Object来讲,equals与==是一样的。

2)对于其它类来说,可以根据需要,在自定义的类中重写(Override) equals方法,实现内容是否相等的逻辑,因为String类重写了equals方法,所以我们才说String的equals比较的是两个字符串的内容,内容就是"abc",第一个new出来的时候传入构造方法的实参就是"abc",第二个字符串常量也是"abc",它们虽然是两个不同的对象,但是它们的内容相同,所以s1.equals(s2)返回真,它们相等。

我再给你写一个,String s3 = "abc"; String s4 = new String("abc");
s2 == s3 是真是假?
答案是true,注意,Java虚拟机 对于内存数据区里面的内容有一个优化,如果已经存在了,不会分配第二个,上面已经 String s2 = "abc";了, 这个"abc"已经存在了,下面String s3 = "abc"; 就不会分配第二个"abc"了,那么s3指向谁?s3也指向上面s2指向的这个对象,现在是s2和s3同时指向同一个对象,那么它们的地址当然一样,==比较的是引用地址,所以s2 == s3 返回true。
s2.equals(s3) 呢? 都是同一个对象了,那自己和自己内容还能不一样?返回true。

s1 == s4 是真是假?
答案是false,注意,使用new关键字生成的对象分配在内存的堆区(heap),并且只要是用了new关键字了,不管你new多少个,内容是否一样,它们都是不同的对象,new一个就出现一个新的,所以s4指向的这个对象,和s1指向的这个是两个不同的对象,地址不同, 因此s1 == s4为false,使用equals比较返回true,因为内容相同。

Java中关于equals()和hashCode()的问题

在Java的类集中比较两个对象是否相等时,为什么既要覆写equals()方法,又要覆写hashCode()方法?只覆写equals()方法之后就可以比较出两个元素是否相等啊,为什么还要覆写hashCode()方法呢?

其实我觉得哈, 这应该是一种惯例.
就是大家的一种共识, 便于以后的拓展和维护.
这样说吧, 你如果只是测试, 那么你随便怎么写都行, 你只要一个equals方法而不管hashcode, 这样OK, 没问题, 程序一样能跑通.
但是, 如果你写了equals方法, 而你不重写hashcode方法, 那么在使用hashtable或hashset的时候, 就会出现很多不必要的错误.
而且..你在重写这两个方法前, 必须要搞清楚, 它们分别应该遵循什么原则, 这也算惯例吧.
比如equals方法, 以下就拷贝了, 很基础的知识.
* 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
* 反射性:x.equals(x)必须返回是“true”。
* 类推性:如果x.equals(y)返回是“true”,而且 y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
* 还有一致性:如果 x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
* 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
hashCode()的返回值和equals()的关系如下:
* 如果x.equals(y)返回“true”,那么x和y的 hashCode()必须相等。
* 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
参考技术A equals比较的是变量中存储的内容 hashcode比较的是在内存中地址只有equals和hashcode返回的都是true 两个变量才可以"=="至于怎么比较内容 重写equals方法就是 参考技术B 比较两个引用是否是同一个地址,也就是说判断他们是不是只向同一个对象

hashCode的用处在于快速判断两个对象是否相等。

a.equals(b)则一定要有a.hashCode() == b.hashCode();

所以如果a.hashCode()!= b.hashCode()则说明 a.equals(b)== false

两者的作用是一样的,没有说一定要一起同时使用,我平时用a.equals(b)来比较两个字符串是否相等。这种常用
参考技术C 如果你只覆盖了equals的话,是会有问题的。因为那就不是重写超类的方法了。在超类中,默认你继承重写的就得是hashCode()跟equals()两个方法,不然就没有效果的。当然,你也可以自己写个equals这样的方法,但其实是不同的。

以上是关于书里说用equals来比较,但是用==也没问题啊,比较结果是一样的,请教一下有啥区别呢?的主要内容,如果未能解决你的问题,请参考以下文章

5214. 最长定差子序列

关于java中equals方法的疑惑

从0开始自制解释器——综述

Java 基础 - 比较方式选择(什么类型用equals()比较,什么类型用==比较)

关于LaTex的安装

简述java中equals()方法和==的区别