class A {
String s4 = "abc";
static public void main(String[]args ) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
A o = new A();
String s5 = new String("def");
System.out.println("s1==s2 : " + (s1==s2));
System.out.println("s1==s1.intern : " + (s1==s1.intern()));
System.out.println("s1==s3 : " + (s1==s3));
System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern()));
System.out.println("s1==s4 : " + (s1==o.s4));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
s1==s2 : true
s1==s1.intern : true
s1==s3 : false
s1.intern==s3.intern : true
s1==s4 : true
Run Code Online (Sandbox Code Playgroud)
我的问题:
1.会发生什么"String s1 = "abc"?我猜String对象是作为一个实习字符串添加到类String中的池?放在哪里?"永久生成"或只是堆(作为String Class实例的数据成员)?
2.会发生什么事"String s2 = "abc"?我想没有任何对象被创建.但这是否意味着Java Intepreter需要搜索所有被拦截的字符串?这会导致任何性能问题吗?
3.Seems String s3 = new String("abc") 不使用实习字符串.为什么?
4.会String s5 = new String("def")创建任何新的实习字符串吗?
该编译器创建"ABC"的String对象常量池中,并生成字节码的赋值语句对它的引用.
见(1).没有搜索; 没有性能问题.
这会在运行时创建一个新的String对象,因为这就是'new'操作符的作用:创建新对象.
是的,对于"def",但由于(3)在运行时也创建了一个新的String.
3-4处的String对象未被实现.
1.“String s1 =”abc”会发生什么?
在编译时,文字的表示形式将写入包含此代码的类的类文件的“常量池”部分。
加载类时,将读取类文件常量池中字符串文字的表示形式,并从中创建一个新的 String 对象。然后该字符串被保留,并且对保留字符串的引用被“嵌入”到代码中。
在运行时,对先前创建/保留的字符串的引用被分配给s1。(执行此语句时不会发生字符串创建或驻留。)
我猜想 String 对象作为实习字符串添加到 String 类的池中?
是的。但在执行代码时则不然。
它放置在哪里?“永久代”还是只是堆(作为 String 类实例的数据成员)?
它存储在堆的 permgen 区域中。(String 类没有静态字段。JVM 的字符串池是在本机代码中实现的。)
2.“String s2 =”abc”会发生什么?
加载时什么也没有发生。当编译器创建类文件时,它为该文字重用了与第一次使用该文字时使用的相同的常量池条目。因此,该语句使用的 String 引用与上一个语句使用的 String 引用相同。
我猜没有创建任何对象。
正确的。
但这是否意味着 Java 解释器需要搜索所有内部字符串?这会导致任何性能问题吗?
否,并且否。Java 解释器(或 JIT 编译代码)使用与为前一条语句创建/嵌入的相同引用。
3.似乎 String s3 = new String("abc") 没有使用 interned string。为什么?
实际情况比这更复杂。构造函数调用使用interned 字符串,然后创建一个新 String,并将 interned 字符串的字符复制到新 String 的表示形式。新创建的字符串被分配给s3。
为什么?因为new被指定为总是创建一个新对象(参见JLS),并且String构造函数被指定为复制字符。
4. String s5 = new String("def") 会创建任何新的实习字符串吗?
在加载时创建一个新的内部字符串(对于“def”),然后在运行时创建一个新的 String 对象,它是内部字符串的副本。(有关更多详细信息,请参阅前面的文字。)