【问题标题】:Why the classname contradicts with interned string comparison using "=="?为什么类名与使用“==”的内部字符串比较相矛盾?
【发布时间】:2013-11-08 07:25:49
【问题描述】:
class helloworld
{
   public static void main(String args[]) {
       String str1="hello";
       String str2="world";
       String str=str1+str2;
       str.intern();
       System.out.println(str=="helloworld");
   }
}  

o/p: 假

执行程序后,它会产生 false 作为输出。如果使用 equals() 而不是 "==" 它返回 true。为什么会这样?

2.在这种情况下,更改类名后,它会产生 true 作为输出。

class main
{
   public static void main(String args[]) {
       String str1="hello";
       String str2="world";
       String str=str1+str2;
       str.intern();
       System.out.println(str=="helloworld");
  }
} 

o/p:true

为什么使用 "==" 与类名进行黑白字符串比较会发生矛盾(如果比较字符串名称用作类名)?

【问题讨论】:

  • 查找字符串实习
  • 这只是让你放弃使用 == 并使用 String.equals()
  • 其实这是一个非常有趣的问题,+1。伙计们,这不是您的想法,请参阅@DavidWallace 的回答。
  • 这是一个非常有趣的问题。否决它的唯一原因是未能理解它。
  • 有人试过上面给出的例子吗?对我来说,无论如何都会产生“假”!

标签: java classname string-interning


【解决方案1】:

原因是在第一个示例中,字符串"helloworld" 已经在字符串池中,因为它是类的名称。所以实习它不会向字符串池添加任何内容。所以str不会是interned值,比较会是假的。

在第二个示例中,str.intern() 实际上将str 添加到字符串池中,因为"helloworld" 不存在。然后,当遇到"helloworld" 文字时,实际使用的字符串对象就是字符串池中的对象。这只是str,所以比较是正确的。

【讨论】:

  • @david 类名也被存储到字符串池呃?
  • 是的,类名进入字符串池。我不知道为什么。
  • 这也让我很模糊
  • 原因可能是当类加载器在已经加载的类中查找类的定义时,可以使用== 而不是equals。我猜这对性能有好处,因为每当字节码包含对任何类的任何引用时,类加载器都需要进行这种比较。换句话说,一直。
  • @Gyro Gearless:intern() 在 Java 6 和 Java 7 之间的行为有所不同。我认为这是因为在 Java 6 中 String 可能是较大 @ 的子字符串987654332@——或者只是实现的简化。然而,在我测试的 Java 7 实现中,它总是返回 true,因此类名没有添加到常量池中,换句话说,str=="helloworld" 返回了 true,而 str==helloworld.class.getName() 返回了 false。文字是在第一次使用时添加的,因此在方法的开头放置 String dummy="helloworld"; 会改变游戏规则。
【解决方案2】:

String 是不可变的。您必须使用str.intern() 的返回值。只是调用str.intern() 并忽略返回值什么都不做。

str = str.intern();

【讨论】:

    【解决方案3】:

    补充答案,这里有一篇关于实习生()的好文章

    英文:https://weblogs.java.net/blog/2006/06/26/all-about-intern

    俄语:http://habrahabr.ru/post/79913/

    【讨论】:

      【解决方案4】:

      不可变对象中的字符串。并且作为 javadoc 的 intern() 函数

      When the intern method is invoked, if the pool already contains a
      string equal to this <code>String</code> object as determined by
      the {@link #equals(Object)} method, then the string from the pool is
      returned. Otherwise, this <code>String</code> object is added to the
      pool and a reference to this <code>String</code> object is returned.
      

      所以你必须分配返回值例如string = string.intern();

      至于你的输出应该是true,不管你的类名是什么,因为如上所述它与调用intern()无关。

      【讨论】:

      • 问题问为什么在这两种情况下不一样。断言它应该是相同的并不能回答这个问题。 -1.
      • @aniket 通过制作 str=str.intern();返回 true 但为什么类名与 str.intern() 相矛盾; ?
      • 大卫在答案中发布的内容在逻辑上听起来是正确的,但我希望我能在字符串池中看到字符串(类名)。当我尝试时,我在这两种情况下都是正确的(我使用的是 Java 7)。如果您真的得到了您发布的行为,那么 Davids 的回答可能是最好的解释,但我建议您在另一个环境中尝试。
      • 在java 7中可能是类名没有添加到字符串常量池中。你的回答很有帮助(:
      猜你喜欢
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 2021-04-02
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多