String字符串存放位置(常量池)
程序计数器(Program Counter Register)程序计数器是一块很小的内存区域,可以当成当前线程所执行的字节码的行号指示器.java解释器通过改变计数器值来选取下一条指令.分治,循环,跳转,异常处理,线程恢复等需要依赖计数器完成特点:每一个线程都有一个独立的程序计数器,互不影响.(线程私有)线程执行Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址.线程执行Na...
·
为什么要用到常量池:
在Java中只要是new的信息都会在堆上开辟一个新的空间,为了解决这个问题,JVM中才出现了字符串常量池的概念。但是只有直接用 ""修饰的字符,才会被加入到常量池中,当再次用 ""创建的时候,会首先从常量池中去获取。
字符串常量池存在于运行时常量池中。也就存在于方法区中。
public class DemoStringCreation {
public static void main(String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
String str5 = "Hel" + "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
运行结果如下:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。
String s = new String("abc"); //创建了几个对象
两个;
第一个对象是"abc"字符串存储在常量池中;
第二个对象是创建在Heap中的String对象;这里的s是放在栈里面的指向了Heap堆中的String对象。
String s1 = new String("s1") ;
String s2 = new String("s1") ; //创建了几个对象
三个;
第一个是编译期就已经创建在常量池中创建的"s1",因为创建一个之后常量池中就会有,不再创建,直接指向;
后面两个是运行期使用new创建在堆上的s1和s2;
String.intern()的使用
new 出来的 String 类型是否也能使用常量池呢? 当然可以,就是通过 intern 方法。这个方法的意思就是先到缓存中(也就是常量池中)查询当前对象是否存在,存在就返回常量池中地址,不存在就加入常量池。
//双引号直接放入常量池
String s1 ="1";
String s2 =newString("1");
//false
System.out.println(s1 == s2);
//先到常量池中查询是否有”1“,存在就将常量池中对象返回,不存在就放到常量池中(此时常量池中存在s1)
//于是就将s1的值重新复制给s3,所以s1 == s3
String s3 =newString("1").intern();
//true
System.out.println(s1 == s3);
String t1 = new String("2");
解析:创建了两个对象,t1指向堆区
String t2 = "2";
解析:t2指向字符串常量池
t1.intern();
解析:字符串常量池已经存在该字符串,直接返回;
System.out.println(t1 == t2); //false or true
解析:很明显 false
String t3 = new String("2") + new String("2");
解析:过程同问题1 t3指向堆区
String t4 = "22";
解析:t4 在1.6 和 1.7中指向不同
t3.intern();
解析: 字符串常量池中已经存在该字符串 直接返回
System.out.println(t3 == t4); //false or true
解析: 很明显为 false 指向不同的内存区
更多推荐
已为社区贡献8条内容
所有评论(0)