Java中的对象比较
来源:互联网 发布:熔炉的真实事件 知乎 编辑:程序博客网 时间:2024/05/22 06:39
关于Java中的数值比较
首先明确一点:
“==” 永远是在比较地址,而equals是比较内容的值。
当我们书写这样的代码:
int a = 10;int b = 10;
JVM 其实是在栈(栈帧中的操作栈?)中查找 3 这个常量,如已经存在了,变量 a 的引用就指向存放 3 的地址,如果没有,就创建一个。因此给基本数据类型的变量赋值时,若它们的值相等,那它们在内存中的地址也相等。a == b
看似是值的比较,实际上也是常量地址的比较。
包装类的比较
以Integer
举例,看一下代码:
Integer n1 = 100;Integer n2 = 100;Integer n22 = Integer.valueOf(100);Integer n222 = new Integer(100);Integer n3 = 1000;Integer n4 = 1000;System.out.println(n1==n2); // trueSystem.out.println(n1==n22); // trueSystem.out.println(n1==n222); // falseSystem.out.println(n3==n4); // false
从输出结果可以看到,直接赋值 和使用 valueOf()
赋值的方式,两个变量的比较结果都是 true
,但是 new
一个新的对象来比较就是 false
。这是为什么呢?
从自动拆装箱机制中可以了解到,直接给包装类赋值其实就是执行了 valueOf()
方法,然后我们又知道 ==
比较的是两个对象的引用地址,这说明直接赋值和使用 valueOf()
方法没有改变对象的引用地址,因此比较结果是 true
。而 new
一个新对象肯定有不同的地址,所以比较结果是false
。看一下Integer的源码:
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property // 最大值 high 可以被修改 ...省略 } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); ...省略 }}public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
这个 IntegerCache
是 Integer
的静态内部类(嵌套类),而 cahce
是一个数组,作为一个常量池,顺序存储了最小值 low(-128)
到最大值 high(127)
之间的所有整数的 Integer
对象。从源码中可以看出,当 i
的值在 [ low, high ] 范围内时,直接返回数组中对应值的地址,否则就创建一个新的对象。
因此前面 n1==n2
的结果是 true
,而 n3==n4
的结果是 false
,因为 n1
、n2
都是引用数组 cache
中100这个值的地址,而1000超过了范围,因此创建了新的对象,引用的地址就不一样了。
有常量池设置的包装类及其范围有:
- 其中
byte
占8位的,可以表示的值也是在 [ -128, 127 ] 范围内,所以任何Byte
对象比较结果都是true
。 Integer
常量池的的最大值high
可以通过JVM的参数设置来修改(从源码上看应该是这样),默认值是127。Character
中常量池保存的是字符编码中,0 到 127 的字符。
而 Float
、Double
因为值是不连续的,所以不设置常量池,Boolean
也没必要设置常量池。
String 的比较
String
类也维护有缓冲池,给对象赋值时,会把字符串加入到缓冲池中,下次赋值时,若缓冲池中含有相同内容的字符串对象,则直接指向它在缓冲池中的地址。
String s1 = "hello";String s2 = "hello";System.out.println(s1==s2); // trueString s3 = "hel";String s4 = "lo";String s5 = "hel" + "lo";String s6 = s4 + s5;System.out.println(s1==s5); // trueSystem.out.println(s1==s6); // false
在给 s1
赋值后,对象被加入到 String
类的缓冲池中,因此在给 s2
赋值时,s2
的引用直接指向缓冲池中内容为”hello”的对象地址,因此 s1==s2
的结果自然就是 true
了。
编译阶段编译器会把两个字符串合成一个,因此 s1==s5
的结果也是 true
。但编译器不会把两个对象合并,因此 s1==s6
的结果是 false
,以为它们的引用地址不相同。
- java中的对象比较
- Java中的对象比较
- java 中的对象比较
- java 集合类中的对象如何比较
- php5中的对象比较
- java中的对象比较 == 和equals
- Java比较器给List中的对象排序
- JAVA [ 类对象比较 ]
- Java对象的比较
- Java-对象比较器
- java 对象比较
- Java 对象比较
- Java 对象的比较
- java对象的比较
- java对象比较
- Java对象比较
- Java 对象比较
- 比较两个Java对象
- 第十周项目1(1)-层次遍历算法的验证
- 博客目录
- ADB server didn't ACK 问题解决方式
- $http
- 第十周项目一
- Java中的对象比较
- 今天什么都不想说,静静的看就好了
- CSS Hack技术详解,支持IE 6-11、Chrome、FireFox、Safari、Opera
- GPIO模拟I2C程序实现
- 也许我们不是最优秀的人才,但我们要做最努力的人
- 关于把PHP模版引擎smarty2升级到smarty3的一些见解
- HTML学习02-排版相关标签
- android 修改应用图标简例
- 数据类型和 Java 基础面试问题(一)