package 字符串;
/**
* @author pp
*/
import jdk.swing.interop.SwingInterOpUtils;
/**
* java中字符串的内存分布问题:
* 在Java中,通过字符串常量、字量面和String类下的intern()方法创建的字符串都有可能被存储到常量池中。 常量池位于堆之外
* 但是只要是直接用new创建的String对象那么字符串就会被存在堆区 或者用字符串拼接的方式创建时其中含右用new创建的字符串或者其他包装类型的时候就会在创建在堆区
* 需要注意的是:虽然一些包装类型在一定范围之内的数据是储存在常量区的,但是利用+和字符串拼接的时候他们会调用toString()方法在堆区创建一个字符串
* 就算用new创建一个空字符串String s=new s(""); 然后用字面值与他拼接 也会在堆区重新创建一个空间
*String 中的intern方法是将创建的字符串对象强制加到字符串常量区(如果字符串常量区没有该常量的话)返回的是在字符串常量池中对饮的引用
*/
public class StringMemory {
public static void main(String[] args) {
String s1 = new String("123");//最开始的时候常量池中没有"123"字符串存在堆区
String s2 = "123";//用字面值创建字符串 此时常量池中没有"123" 那么会在常量池中存入"123"
String s3 = String.valueOf(123);//调用的是包装类型Integer的toString()方法
String s4 = new String("123");
String s5 = "123";
String s6 = "1" + "23";
String s7 = "" + s1;
String s8 = String.valueOf(s1);
String s9 = String.valueOf("123");
String s10 = "";
String s11 = new String("");
String s12=new String("456");
s12.intern();
String s13="456";
System.out.println(s12==s12.intern());//false
System.out.println(s12==s13);//false
System.out.println(s12.intern()==s13);//true
/*
String s2 = String.valueOf(123);
这一句其实是调用的如下方法:
public static String valueOf(int i) {
return Integer.toString(i);
}
-->
public static String toString(int i) {
int size = stringSize(i);
if (COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
//观察包装类型Integer中重写的toString()方法发先最终使用的关键字new 创建的String对象 所以字符串也是储存在堆区
*/
/*
String s8=String.valueOf(s1);
这句调用的方法如下:
String s8=String.valueOf(s1);
String s9=String.valueOf("123");
-->
public String toString() {
return this;
}
*/
/*
String s9 = String.valueOf("123");
这句调用的方法如下:
String s8=String.valueOf(s1);
String s9=String.valueOf("123");
-->
String temp="123";
-->
public String toString() {
return this;
}
*/
System.out.printf("s1和s2的地址是否相同:%s\ns1和s3的地址是否相同:%s\ns2和s3的地址是否相同:%s" +
"\ns1和s4的地址是否相同:%s\ns2和s4的地址是否相同:%s\ns2和s5的地址是否相同:%s\n" +
"s2和s6的地址是否相同:%s\ns2和s7的地址是否相同:%s\ns1和s7的地址是否相同:%s\n" +
"s1和s8的地址是否相同:%s\ns2和s8的地址是否相同:%s\ns1和s9的地址是否相同:%s\n" +
"s2和s9的地址是否相同:%s\ns10和s11的地址是否相同:%s\n"
, s1 == s2, s1 == s3, s2 == s3, s1 == s4, s2 == s4, s2 == s5,
s2 == s6, s2 == s7, s1 == s7, s1 == s8, s2 == s8, s1 == s9,
s2 == s9,s10==s11);
/*运行结果如下:
false
false
true
s1和s2的地址是否相同:false
s1和s3的地址是否相同:false
s2和s3的地址是否相同:false
s1和s4的地址是否相同:false
s2和s4的地址是否相同:false
s2和s5的地址是否相同:true
s2和s6的地址是否相同:true
s2和s7的地址是否相同:false
s1和s7的地址是否相同:false
s1和s8的地址是否相同:true
s2和s8的地址是否相同:false
s1和s9的地址是否相同:false
s2和s9的地址是否相同:true
s10和s11的地址是否相同:false
*/
}
}
关于常量池:
这里给大家推荐一篇超级超级超级好的文章: