如果我将String
字面值传递给某些metohd:
String s=new String("stack");
String s2=s.concat("overflow");
将存储字符串“overflow”。
我的一个朋友认为它是在String
恒定池中创建的,我反对他。
请让我知道
提前致谢。
答案 0 :(得分:3)
所有String
文字都在常量池中。结束。在这种情况下,两个常量"stack"
和"overflow"
进入池中。创建一个新的String
,它与池中的"stack"
保持相同的值,然后通过将常量池中的String
连接到它来创建另一个"overflow"
。
摘录自javap -c -verbose Test
:
Constant pool:
#1 = Methodref #10.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // java/lang/String
#3 = String #21 // stack
#4 = Methodref #2.#22 // java/lang/String."<init>":(Ljava/lang/String;)V
#5 = String #23 // overflow
#6 = Methodref #2.#24 // java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
答案 1 :(得分:0)
这个问题肯定是不可判定的,但你可以找到java编译器和JVM的某种组合是如何做到的。
据我所知,没有什么能阻止编写一个java编译器,当它看到一个字符串常量时,会发出字节代码,以某种方式在堆中创建该字符串 long 因为JLS中关于字符串文字的规则仍然存在。例如,String.intern
可以维护一个全局Map,编译器可以编译一个String文字,如下所示:
create a char array of the desired size
put character at index 0
put character at index 1
...
put character at index (length-1)
construct the actual string object
pass the String just created to String.intern and leave result on the stack
实际上,可以让预处理器将所有字符串常量更改为
(extra.HeapString.createString(new char[] { ... }))
并让createString
创建一个String实例,使String文件的规则成立。并且您无法编写一个程序来检测它是从原始源编译还是从预处理源编译(除了extra.HeapString
上的反射)。
答案 2 :(得分:-1)
字符串stack
将在堆中,字符串overflow
在常量池中,第三个字符串作为常量池中串联stackoverflow
的结果。