标签:
1、Integer
public static void main(String[]args) { Integer i=new Integer(1); System.out.println(i.intValue()); i=2; System.out.println(i.intValue()); }
我们知道Integer的属性value的类型为:final int value;
而方法intValue就是返回value。
很显然,上面两次打印结果是不同的,而都是同一个引用变量i。然道我们对置为1的Integer实例做了修改,将其value值变成了2?
很显然,这种结论是不正确的,因为它违反了final修饰变量的特性。
1 public class Test { 2 public static void main(String[]args) { 3 Integer i=new Integer(1); 4 System.out.println(System.identityHashCode(i)); 5 i=2; 6 System.out.println(System.identityHashCode(i)); 7 } 8 }
通过这段代码,可知,value值为1的实例和value值为2的实例是两个不同的实例。正如上说,因为value属性是由final修饰的,因此这个类是不可变的。
内存空间释义图如下:
由释义图可知,改变了value值,其实就是新生成了一个空间,改变引用变量的指示方向;而原先那个value值为1的实例就变成了游离的实例,成为java虚拟机回收的对象目标。正因为,要想改变value就得重启一个空间,这是比较消耗性能的,因此Integer会对[-128,127]范围类的值的实例缓存下来。
2、String
其属性类型为final char value[];
因此String类也是不可变的。
和Integer一样,改变value值就得新开辟一个空间,这也是性能上的一种消耗,因此,Java给String的字面量也提供了缓存,如果某个字符串的字面量能够
在缓存池当中找到那么就会复用(编译阶段完成的)。
1 public static void main(String[]args) { 2 String str1="feijishuo"; 3 String str2="feijishuo"; 4 System.out.println(str1==str2); //true 5 6 String str3="feiji"; 7 String str4="fei"; 8 String str5="ji"; 9 String str6="fei"+"ji"; 10 String str7=str4+str5; 11 System.out.println(str3==str6); //true 12 System.out.println(str3==str7); //false
13
14 final String Str8="fei";
15 String str9=str8+"ji";
16 System.out.println(str3==str9); //true
17 }
代码分析:str1和str2指向同一个实例,那是因为字面相同,它们会存在于缓存池(编译时常量池)当中。
str3和str6指向同一个实例,因为字面量“fei”和“ji”在编译时就确定下来了,那么str6在编译时候也能确定下来,然后这个字面量已经在
缓存池(编译时常量池)当中存在了,因此就不用生成新的实例了,只要将引用变量指向存在的实例即可。
str3和str7不是同一个实例,因为变量只有在运行期间才能知道其所指示的值。
str3和str9是同一个实例,因为变量str8定义为final类型的,因此其在编译期间就能确定下来。其实例已经存在常量池(编译时常量池)当中
存在,因此不会生成新的实例。于是,构成str9的式子都能在编译期间在常量池中找到,因此str9在编译期间也就确定了下来,其实例在常量池中已经存 在。
标签:
原文地址:http://www.cnblogs.com/feijishuo/p/4560963.html