Java中的字符串(转的,摘录)再结合百度百科常量池的理解

拘留字符串对象
源代码中所有相同字面值的字符串常量只可能建立唯一 一个拘留字符串对象。 实际上JVM是通过一个记录了拘留字符串引用的内部数据结构来维持这一特性的。在Java程序中,可以调用String的intern()方法来使得一个常规字符串对象成为拘留字符串对象。
(1)String s=new String("Hello world");       编译成class文件后的指令(在myeclipse中查看):
事实上,在运行这段指令之前,JVM就已经为"Hello world"在堆中创建了一个拘留字符串( 值得注意的是:如果源程序中还有一个"Hello world"字符串常量,那么他们都对应了同一个堆中的拘留字符串)。然后用这个拘留字符串的值来初始化堆中用new指令创建出来的新的String对象,局部变量s实际上存储的是new出来的堆对象地址。
(2)String s="Hello world";
这跟(1)中创建指令有很大的不同,此时局部变量s存储的是早已创建好的拘留字符串的堆地址。
 
 
八种基本类型的包装类和对象池  java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用常量池,也即对象不负责创建和管理小于127的这些类的对象。   一些对应的测试代码:
public class Test{ public static void main(String[] args){
//5种整形的包装类Byte,Short,Integer,Long,Character的对象,
//在值小于127时可以使用常量池
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2); //输出true
//值大于127时,不会从常量池中取对象
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4); //输出false
//Boolean类也实现了常量池技术
Boolean bool1=true;
Boolean bool2=true;
System.out.println(bool1==bool2); //输出true
//浮点类型的包装类没有实现常量池技术
Double d1=1.0;
Double d2=1.0;
System.out.println(d1==d2); //输出false
}
}
对Integer对象的代码补充
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) {
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
当你直接给一个Integer对象一个int值的时候,其实它调用了valueOf方法,然后你赋的这个值很特别,是128,那么没有进行cache方法,相当于new了两个新对象。所以问题中定义a、b的两句代码就类似于:
Integer a = new Integer(128);
Integer b = new Integer(128);
这个时候再问你,输出结果是什么?你就知道是false了。如果把这个数换成127,再执行:
Integer a = 127;
Integer b = 127;
System.out.println(a == b);
结果就是:true
进行对象比较时最好还是使用equals,便于按照自己的目的进行控制。这里引出equals()和==,equals比较的是字符串字面值即比较内容,==比较引用。
看一下IntegerCache这个类里面的内容
private static class IntegerCache {
private IntegerCache() {
}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
由于cache[]在IntegerCache类中是静态数组,也就是只需要初始化一次,即static{......}部分,所以,如果Integer对象初始化时是-128~127的范围,就不需要再重新定义申请空间,都是同一个对象---在IntegerCache.cache中,这样可以在一定程度上提高效率。
 
 
 
总结:所有引用数据类型都是指向堆中的一块空间。当Integer类型的时候,
Integer i1=127;
Integer i2=127;
常量池里面放的是int类型的127(小于127和大于-128)的时候 执行一次new Integer(127) 分别将引用赋值给i1和i2;
Integer i3=128;
Integer i4=128;
常量池里面放的是int类型的128(大于127和小于-128)的时候 有多少就new多少次,分别赋值给i3和i4;
初始化估计是用常量池中的值
 
String s="Hello world";
当String类型的时候,常量池中有多个一样的(或者理解为常量池中不能放入重复的值)只产生一个拘留字符串,会在堆中开辟一个空间存入该字符串,(称为拘留字符串),然后将拘留字符串的引用赋值给s,
String s=new String("Hello world"); 如果这样就相当于新的new出来了一个堆空间,然后用拘留字符串将其初始化。再将新new出来的引用赋值给s