当前位置: 首页 > 面试题库 >

使用Java在编译时完成字符串实习吗?

戈嘉慕
2023-03-14
问题内容

我对Java中字符串实习的工作方式感到困惑。当我写:

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

if (a==b)
    System.out.println("Equal");

编译器在编译时是否将字符串文字“ ABC”存储到字符串常量池中?

这听起来是不合逻辑的,因为我认为字符串常量池是由JVM在运行时创建的,而且由于Java编译器甚至没有调用JVM,所以我不知道如果在编译时完成字符串常量池是怎么可能的。

如果它不是在编译时完成的,而是在运行时完成的,那么以下内容为什么返回false(从此答案中获取)?

// But .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) // --> false

如果在运行时完成,那么JVM为什么不能弄清楚它们是相同的字符串?

我对Java中的字符串实习如何工作以及Java字符串池的确切存储位置感到困惑。


问题答案:

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

如果在运行时完成,那么JVM为什么不能弄清楚它们是相同的String。

因为返回的字符串.substring尚未被求值,所以"test"与字符串池中的等效字符串不同的对象也是如此。如果实习,您将得到true

"test" == "!test".substring(1).intern() // true

JLS的第4.4节和JVM规范的第5.3节看起来很相关。

明确一点:在Java中比较字符串的正确方法是使用.equals方法或类似方法,而不是====与字符串实例一起使用 通常是
不正确的。(除非您正在玩弄什么时候以及如何进行实习……)



 类似资料:
  • 我正在学习如何通过OCA考试,并坚持这个java字符串池的概念。 考虑以下几点: 和在字符串中是相同的,在对象中也是相同的,因为它是相同的字符串文本,所以JVM在编译时将字符串池和。 现在,是在运行时计算的,因此应该返回一个新字符串。因此,应该为false,但事实并非如此。为什么? 我的一个理论是方法首先检查是否有空白需要删除,如果没有,则简单返回本身。这可以解释为什么s1==s3,但我不确定。

  • 我很好奇为什么下面的代码: 当使用编译时,生成以下代码: 当使用相同的编译时。我不明白为什么它不能识别仍未使用,而不管字符串长了一个字节。 这个问题与GCC9.1和CLANG8.0(在线:https://gcc.godbolt.org/z/p1z8ns)相关,因为在我看来,其他编译器要么完全删除未使用的变量(ellcc),要么为其生成代码,而不管字符串的长度如何。

  • 问题内容: 以下两段代码是否相同? 问题答案: 它们具有相同的 最终结果 ,但它们并不相同(它们将产生不同的字节码;版本实际上经过了这些步骤,生成了新的字符串对象,然后对其进行中间化)。 来自以下两个相关引号: 调用该方法时,如果池中已经包含与该方法确定的对象相等的字符串,则返回池中的字符串。否则,将此对象添加到池中,并返回对该对象的引用。 所有文字字符串和字符串值常量表达式都将被插入。 因此,

  • 问题内容: 问题1 在第一种情况下,我知道这是两个字符串文字的串联,因此将对结果“ I Love Java”进行检查,使结果为true。但是,我不确定第二种情况。 问题2 上面的返回false,但是如果我注释掉第1行和第2行,则返回true。这是为什么? 问题答案: 问题的第一部分很简单:Java编译器将多个字符串文字的串联视为一个字符串文字,即 和 是两个完全相同的字符串文字,可以正确地进行in

  • 上面的代码返回false,但是如果我注释掉第1行和第2行,它返回true。为什么会这样?

  • 经过上一步的漫长等待,不出意外的话都能出包了。 完整刷机包的位置是: ~/android/sudamod/out/target/product/z2_plus/sudamod-71.2-xxxxxxxxxxxx-UNOFFICIAL-z2_plus.zip 把这个包刷入手机就好用了。 在这个目录下,还会有一个同名的 md5sum 文件,推荐把它一起放入手机,这样 recovery 刷入时会自动检测