网上看到一家公司的一道面试题:“你是如何理解==与equals的?”
面试的兄弟支支吾吾半天没回答到重点。结果可想而知了~~~
这道题在笔试中的出镜率相当高,下面一起来看看。
一:==
1. 如果是基本数据类型的比较,则比较的是值
int a = 1000;
int b = 999;
if(a == b){
System.out.println("a == b");
}
这里 == 比较的是a的值1000和b的值999是否相当
基本数据类型:
byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。
short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。
int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有true和false两个取值。
char:16位,存储Unicode码,用单引号赋值。
如果 == 用于以上八种基本数据类型比较的时候,比较的是值。
2: 如果是包装类或者引用类的比较,则比较的是对象地址。
User user1 = new User("张三",20);
User user2 = new User("老田",20);
if(user1 == user2){
System.out.println("老田就是张三");
}
这时候比较的是user1指向的地址和user2指向的地址是否一致 。
二、equals
网上都说,equals是比较的是内容,这是不对的,具体问题具体分析
1: 没有重写equals方法
//以下是源码
public boolean equals(Object anObject) {
//同一个对象地址,直接返回true
if (this == anObject) {
return true;
}
return false;
没有重写,Object中的equals方法,比较的就是两个对象的地址
(就是使用==来比较的)
举例:
自定义的对象就是object类,测试代码如下:
private Long id;
private String userName;
public User() {
}
public User(Long id, String userName) {
this.id = id;
this.userName = userName;
}
@Test
public void Test() {
User user1 = new User(1l, "小李");
User user2 = new User(1l, "小李");
System.out.println(user1.equals(user2)?true:false);
}
测试结果 :
false
2: 重写equals方法
重写了equals方法后,还得看equals方法是如何写的。
能被识别的数据类型(String/Integer等)源码中都是重写了eqauls方法的。
在Integer中
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
在Integer中 比较的就是对应的数字的值 。
在String中
public boolean equals(Object anObject) {
//同一个对象地址,直接返回true
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
//字符串长度不一直,就直接返回false
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//长度一样的字符串,然后比较字符串中的内容
while (n-- != 0) {
//挨个比较,只要有不一致的就返回false
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
举个例子:
String aa = "abcd";
String bb = "abcde";
aa.equals(bb)
在String中 先是比较地址,地址一样就返回true,地址不一样会根据不同数据类型去执行比较值的方法 。
Integer
和String
中 ==
、equals
代码验证结果如下:
自定义类中重写equals方法
//以下是自定义类
public class User {
private Long id;
private String userName;
public User() {
}
public User(Long id, String userName) {
this.id = id;
this.userName = userName;
}
//equals方法爱怎么写就怎么写
//比如说一个正常的人比较,只要身份证号一样,那就肯定是同一个人了。
//所以在equals的时候我们也可以只比较身份证号就可以了。
@Override
public boolean equals(Object o) {
//同一个对象地址,直接返回true
if (this == o) {
return true;
}
//为null或者Class不一致返回false
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
//当两个对象的id相同并且userName相同才返回true
return Objects.equals(id, user.id) &&
Objects.equals(userName, user.userName);
}
@Override //该方法也要重写,不然无法比较对象hashcode
public int hashCode() {
return Objects.hash(id, userName);
}
}
上面的写法中Objects.equals(id, user.id) && Objects.equals(userName, user.userName)
equals比较的是对象中 id 的值和 userName 的地址
3:再来一种自定义的equals写法
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
上面的写法中 equals比较的是对象的地址。
总结: 对象重写equals,根据不同的属性类型, 可以有很多种不同的比较方法
三、总结
1:==
用于基本数据类型比较的是值
2:==
用于包装类(引用类)比较的是对象地址
3:equals
方法没有重写还是比较对象地址
4:重写equals
方法后要看是如何重写的(Object(地址)、Integer(值)、String(先地址后值、地址不同值相同返回true)、自定义类(可以自己定义)
)
以上就是对equals的所用用法....如果喜欢那就点点赞。。。