Why?
为何如下结果为false呢
Integer ic=128;
Integer id=128;
System.out.println("ic==id结果为:"+(ic==id));
对于对象引用类型:“==”比较的是对象的内存地址。
对于基本数据类型:“==”比较的是值。
对于这个问题就不得不说一下常量池了。常量池分为静态常量池和运行时常量池
静态常量池:即是全局常量池,通常理解为被final修饰的常量。
运行时常量池:是方法区的一部分,用于存放运行时创建的常量。
栗子
Integer ia=127;
Integer ib=127;
Integer ic=128;
Integer id=128;
System.out.println("ia==ib结果为:"+(ia==ib));
System.out.println("ic==id结果为:"+(ic==id));
对于Integer对象来说,其能存储常量的范围为(-128~127),超出范围则存储到堆内存中。127和128都是常量,按照正常情况都会在运行时常量池创建,但是Integer对象类型能够存储常量的范围为(-128~127),所以127被创建在运行时常量池中,而128则创建在堆内存中(这里涉及到Java基本数据类型和封装类之间的自动装箱和自动拆箱)。 例子中的ia和ib都指向同一个常量地址;在堆内存中每个变量都会分配一个内存地址,ic和id在堆内存中的存储地址是不一样的,“==”来比较值就是false。
再来举个栗子
String类
1、没有使用new关键字
String sa="hello world!";//在常量池中建立字符串“hello world!”,然后sa指向该常量池地址
String sb="hello world!";//sb指向该常量池地址
String s1="hello ";
String s2="world!";
String sc=s1+s2;
System.out.println("sa==sb结果为:"+(sa==sb));
System.out.println("sa==sc结果为:"+(sa==sc));
按照之前的分析,字符串“hello world!“会创建在运行时常量池里面,sa和sb用”==“是true,那么sa和sc为何为false呢?
s1和s2都会在运行时常量池里面创建,使用+拼接起来的sc会是什么呢?
将编译好的.class文件反编译如下:
String sa = "hello world!";
String sb = "hello world!";
String s1 = "hello ";
String s2 = "world!";
String sc = (new StringBuilder(String.valueOf(s1))).append(s2).toString();
原来sc是通过StringBuilder来实现拼接的,其指向的是堆内存地址。sa==sc自然是false了。
2、再来看看使用new关键字
String str1=new String("hello world!");
String str2=new String("hello world!");
System.out.println("str1==str2结果为:"+(str1==str2));
字符串”hello world! “会被创建在运行时常量池里面,str1和str2是两个不同的对象,内存地址不一样,但是其引用的都是常量池里面的”hello world! “。因此不能用”==“比较。
总结:比较值是否相等对于基本数据类型使用==比较,对于封装类则用equals比较。
收获:浅简的理解了静态常量池和运行时常量池。