『Java面经』Java中 == 和 equals() 的区别

『Java面经』Java中 == 和 equals() 的区别,第1张

『Java面经』Java中 == 和 equals() 的区别

文章目录
  • 1、==
  • 2、equals
  • 3、Integer与享元模式
    • 3.1 享元模式
    • 3.2 问题解答
  • 4、微信关注『方糖算法』

1、==

简单来说,== 是比较两个对象的内存地址。

  • 对于基本数据类型(byte,short,char,int,float,double,long,boolean),他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的。
  • 在常量池中,基本数据类型和字符串,内容相同则地址相同,比如整数123,与字符串"123",储存在同一块地址,基本类型和字符串可以用 == 直接比较。

试一试

Integer i1=127;
Integer i2=127;
System.out.println(i1==i2);     //true  自动装箱

Integer i3=128;
Integer i4=128;
System.out.println(i3==i4);     // false(是不是很奇怪,往下看)  自动装箱

Integer v1 = Integer.valueOf(28);
Integer v2 = Integer.valueOf(28);
System.out.println(v1 == v2);	// true  自动装箱

Integer v3 = Integer.valueOf(128);
Integer v4 = Integer.valueOf(128);
System.out.println(v3 == v4);	// false  自动装箱

Integer v5 = new Integer(1);
Integer v6 = new Integer(1);
System.out.println(v5 == v6);   //false  

对于基本数据的包装类型(Byte, Short, Character,Integer,Float, Double,Long, Boolean)除了Float和Double之外,其他的六种都是实现了常量池的,因此对于这些数据类型而言,一般我们也可以直接通过==来判断是否相等。

2、equals

equals 也是比较两个对象的内存地址。

对于一个对象来说,他本身就提供了一个 equals 方法:

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

所以不重写这个方法,那比较的就是内存地址。而所有的类都继承 Object 类,所以可以重写equals 来实现自定义比较方法。

3、Integer与享元模式 3.1 享元模式
  • Integer i = 5 自动装箱,通过 Integer.valueOf(5) 方法将 5 封装成 Integer 对象。

从 valueOf 方法看出来,当 i 在 [ -128,127 ] 会从缓存中直接返回,否则就会 new 一个返回。

public static Integer valueOf(int i) {
	if(i >= -128 && i <= IntegerCache.high)
		return IntegerCache.cache[i + 128];	// 在范围内,直接返回
	else
		return new Integer(i);	// 超出范围,new一个
}

IntegerCache 源码:

// 静态数组
private static class IntegerCache {
	static final int high;
	static final Integer cache[];

	static {
		final int low = -128;

		// high 可以通过属性来配置
		int h = 127;
		if (integerCacheHighPropValue != null) {
			// 在这里使用Long.decode,以避免调用以下方法
			// 要求Integer的自动搜索缓存被初始化
			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() {}
}

综上:当自动装箱在 [ -128,127 ] 范围,则不生成新的 Integer,而是共享了一个 Integer 对象。超出该范围的 Integer 才真正的new 出了 Integer 对象。

3.2 问题解答
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2);     //true  自动装箱

为什么是 true ?

i1 = 127 执行了 valueOf 自动装箱,由于 127 在缓存范围内,所以直接共享缓存数组里的对象。
i2 同上,所以 i1,i2 引用了同一个地址。


Integer i3=128;
Integer i4=128;
System.out.println(i3==i4);     // false  自动装箱

为什么是 false?

i3 = 128 执行了 valueOf 自动装箱,由于 128 不在缓存范围内,所以 new 了一个新对象。
i4 = 128 执行了 valueOf 自动装箱,由于 128 不在缓存范围内,所以 new 了另一个新对象。
i3,i4 引用不同的对象,对应不同的地址。


Integer v1 = Integer.valueOf(28);
Integer v2 = Integer.valueOf(28);
System.out.println(v1 == v2);	// true  自动装箱

Integer v3 = Integer.valueOf(128);
Integer v4 = Integer.valueOf(128);
System.out.println(v3 == v4);	// false  自动装箱

这两个同上,只是显示调用 valueOf 方法。


Integer v5 = new Integer(1);
Integer v6 = new Integer(1);
System.out.println(v5 == v6);   //false  

v5 和 v6 直接 new 了一个对象,虽然 1 没有超出范围,但是他们直接 new 了对象,并没有走缓存。所以 v5 和 v6 地址是不同的。

4、微信关注『方糖算法』

各类面试资料、内推资源,关注微信公众号获取哦。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4667856.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-06
下一篇 2022-11-06

发表评论

登录后才能评论

评论列表(0条)

保存