- 1、==
- 2、equals
- 3、Integer与享元模式
- 3.1 享元模式
- 3.2 问题解答
- 4、微信关注『方糖算法』
简单来说,== 是比较两个对象的内存地址。
- 对于基本数据类型(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、equalsequals 也是比较两个对象的内存地址。
对于一个对象来说,他本身就提供了一个 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、微信关注『方糖算法』各类面试资料、内推资源,关注微信公众号获取哦。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)