在Java中,字符串是在编译时进行的吗?

在Java中,字符串是在编译时进行的吗?,java,string,equality,Java,String,Equality,我真的对Java的工作原理感到困惑。当我写作时: String a = "ABC"; String b = "ABC"; if (a==b) System.out.println("Equal"); 编译器是否在编译时将字符串文字“ABC”存储到字符串常量池中 这听起来不合逻辑,因为我认为字符串常量池是由JVM在运行时创建的,如果在编译时创建,我不认为这是可能的,因为Java编译器甚至不调用JVM 如果它不是在编译时完成的,而是在运行时完成的,那么为什么下面的返回false(取自)

我真的对Java的工作原理感到困惑。当我写作时:

String a = "ABC";
String b = "ABC";

if (a==b)
    System.out.println("Equal");
编译器是否在编译时将字符串文字“ABC”存储到字符串常量池中

这听起来不合逻辑,因为我认为字符串常量池是由JVM在运行时创建的,如果在编译时创建,我不认为这是可能的,因为Java编译器甚至不调用JVM

如果它不是在编译时完成的,而是在运行时完成的,那么为什么下面的返回false(取自)

如果是在运行时完成的,那么为什么JVM不能判断它们是同一个字符串


我真的搞不清楚字符串内部处理在Java中是如何工作的,以及Java字符串池的确切存储位置。

编译器将文本字符串放在类文件中(只有唯一的字符串,它合并了所有等效的文本);加载类文件时,JVM将这些字符串加载到字符串池中

如果它是在运行时完成的,那么为什么JVM不能确定它们是相同的字符串呢

因为
.substring
返回的字符串尚未插入,因此与字符串池中的等效
“test”
字符串是不同的对象。如果你实习它,你会得到
true

"test" == "!test".substring(1).intern() // true
部分和部分看起来是相关的


需要明确的是:在Java中比较字符串的正确方法是使用
.equals
方法或类似方法,而不是
=
。将
==
与字符串实例一起使用通常是不正确的。(除非你在玩弄理解实习的时间和方式…

我查过了。上课时间

String a = "ABC";
String b = "ABC";
只发现了一个“ABC”。也就是说,javac在编译时创建一个相同字符串的常量


但是,如果两个或更多的类具有相同的“ABC”常量,那么JVM将把它们放在字符串池中的相同位置。下面的链接很有见地:我不确定问题的第一部分,但是
子字符串
返回一个新对象,因此当两个字符串的内容都与
test
匹配时,因为它们不是同一个对象,
=
返回false。这是编译器。我不明白你为什么说它不能同时把字符串放入字符串常量池。编译器会将常量字符串放入某个内存位置,然后在启动程序时JVM会加载该内存并创建常量池以在运行时使用,但是池是由编译器设置的。在堆栈溢出启动6年后,这怎么不是一个重复?substring@的文档特别说明它返回一个新的字符串对象。只是添加了一些细节。回答得好。@RobertBain:
实习生
不是免费的,是有成本的。调用方可能不希望A)性能开销,和/或B)不希望返回的字符串在池中。我当然不想每次创建子字符串时都在表中查找,也不想将我创建的每个临时子字符串都放在池中。@t.J.Crowder感谢您的详细解释:)@Kramer786:池存储对字符串的引用,这些字符串是以通常方式存储的普通对象。池的目的纯粹是为了避免具有等效字符串的多个副本,而不是将它们放在内存中的其他位置。关于如何找到它们,实现细节仅此而已,因此JVM之间可能会有所不同,但它可能使用B-树或哈希机制或类似机制。
String a = "ABC";
String b = "ABC";