常见代码如下
String str = "rrr";
String str0 = "rrr";
String str1 = str;
String str2 = str + "333";
String str6 = "111" + "333";
String str3 = str.intern();
String str4 = new String("123");
String str6 = "111" + "333";
str6变量在编译的时候可以优化,相当于"111333"字符串常量赋值str6.
String str2 = str + "333";
str2的值相当于常量池创建str,与 "333",并创建拼接上的常量"rrr333",将常量的地址赋予str2.
如果是方法处理
//在JVM编译的时候
public String concatString(String str1, String str2){
return str1+str2;
}
//可能会变成
public void concatString(String str1, String str2){
StringBuilder sb = new StringBuilder();
sb.append(str1);
sb.append(str2);
return sb.toString();
}
Java中,String有字符串常量池的概念,如上"rrr"在运行时,会在常量池建立"rrr"对象,内存地址指向str。
String的value是private final类型,不可改变
除非new String("xxx"),否则如果String值字面量一致(eques),它们的内存地址一致。使用==比较为true,如上,str与str0,str1,str3
String的intern()方法会监测常量池中是否有该字符串的值的字面量,有,返回字符串常量的地址,没有,则新建新建字符串常量并返回内存地址。
String str4 = new String("123");
Java也会监测常量池中是否有“123”字面量,没有,则在常量池中再新建一个“123”的字面量。
使用new关键字新建String对象时,会在堆中新创建一个字符串对象,值为“123”
如果此时比对str4=="123",结果为false。
JVM高级特性
jdk1.7的HotSpot中,将原来在方法区中的静态变量、字符串常量池等移到堆内存中,(常量池包含字符串常量池、class常量池等)
在jdk1.8中,方法区更名元空间(MetaSpace),直接占用的本地内存(NativeMemory)。