Java中equals和==的区别

简单一句话:==表示变量块中的内容相等,equals表示属性相等。

为什么要强调变量块中的内容?其实这里所说变量块中的内容相等其实就是变量相等,但是为了说清楚==,这么说可以更好地区别基本数据类型和引用的情况。

变量块中的内容,无非两种情况,基本数据类型 或者 地址(对对象的引用)。==就是比较这其中的内容是否一致。

Object obj_1 = new Object();
Object obj_2 = new Object();

这就不难理解为什么 obj_1==obj_2 为false了。因为new出来的两个Object在堆中为两个对象,所以obj_1和obj_2中存的地址不一样。

但是基本数据类型不存在这个问题,对于基本数据类型都是直接拿出来,比较值是否相同。

从根本上来说,对于基本数据类型和对象的==没有区别,都是拿变量存的值来进行比较,只要一致那就返回true,不一致就返回false。所以如果变量引用相同的对象,那么其值也相同,返回也为true。

注意==的坑

主要是一些对象创建时会直接返回常量池地址(String)或者堆中已缓存对象(Integer)。

String:
String str_1 = "abc";
String str_2 = "abc";
String str_3 = "ab" + "c";
String str_4 = new String("abc");

str_1=str_2=str_3≠str_4
str_1=str_2都为字符串常量池(在堆中)“abc"的地址。在第一次定义时,常量池中没有"abc"为自动创建。
str_2=str_3是编译器有关,编译器会自动处理这种可处理的常量,在编译后"ab”+"c"和"abc"没有区别。
str_3≠str_4是用new在堆中开辟了一个新的对象。其实在javap后会发现,调用String构造函数的过程也是在字符串常量池中创建了新的字符串常量,然后String对象指向这个常量。相当于str_4->String->“abc”,所以此时str_4为这个String对象的地址。

Integer:

在方法区中,有一个静态类IntegerCache:

private static class IntegerCache {
 static final int high;
 static final Integer cache[];
 static {
 final int low = -128;
 // high value may be configured by property
 int h = 127;
 if (integerCacheHighPropValue != null) {
 // Use Long.decode here to avoid invoking methods that
 // require Integer's autoboxing cache to be initialized
 int i = Long.decode(integerCacheHighPropValue).intValue();
 i = Math.max(i, 127);
 // Maximum array size is Integer.MAX_VALUE
 h = Math.min(i, Integer.MAX_VALUE - -low);
 }
 high = h;
 cache = new Integer[(high - low) + 1];
 int j = low;
 for(int k = 0; k < cache.length; k++)
 cache[k] = new Integer(j++);
 }
 private IntegerCache() {}
 }

当int类型自动装箱时,会调用Integer的valueOf方法:

public static Integer valueOf(int i) {
 if(i >= -128 && i <= IntegerCache.high)
 return IntegerCache.cache[i + 128];
 else
 return new Integer(i);
 }

可以看到valueOf在-128到127直接返回了方法区中的静态Integer。
所以如果通过自动装箱创建两个值相同的Integer,其==是相同的;但是如果通过new创建,就会不同。

Equals

其实equals只是一个类方法,由于java所有类都继承自Object,而Object中实现了equals方法:

public boolean equals(Object obj) {
 return (this == obj);
}

如果不重写类的equals方法,其实和用==没有任何区别。

所以判断内容是否相等最终都要看类的equals方法如何实现,java的api中基本都实现了equals方法。
可以使用lombok中的@EqualsAndHashCode注解来实现自动重写。
属性callSuper=true表示父类属性也要相等,但是会调用父类的equals方法判断,如果父类没有重写,还是调用==,为false。

2024.5.14补充
Integer==int会发生什么?
由于Integer有自动拆箱的特性,当用Integer和int比较时会自动转换成int,所以不存在上述问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值