混淆String引用比较==与实习生

时间:2015-10-24 22:29:36

标签: java string string-comparison string-interning string-pool

我读了这个when should we use intern method of string on string constants,但仍然不太清楚String ==也比较intern()。我有几个例子。有人可以帮助我更好地理解这一点。

String s1 = "abc";
String s2 = "abc";
String s3 = "abcabc";
String s4 = s1 + s2;

System.out.println(s3 == s4);                            // 1. why false ?
System.out.println(s3 == s4.intern());                   // 2. why true ?
System.out.println(s4 == s1 + s2);                       // 3. why false ?
System.out.println(s4 == (s1 + s2).intern());            // 4. why false ?
System.out.println(s4.intern() == (s1 + s2).intern());   // 5. why true ?

3 个答案:

答案 0 :(得分:3)

这里有很多答案可以解释,但是让我给你另一个答案。

只在两种情况下将字符串插入到字符串文字池中:加载类时,字符串是文字或编译时常量。否则仅在您对字符串调用+时。然后,该字符串的副本将在池中列出并返回。所有其他字符串创建将不会被实习。字符串连接(.equals())正在生成新实例,只要它不是编译时常量表达式*。

首先:永远不要使用它。如果您不理解,则不应使用它。使用System.out.println(s3 == s3.intern()); // is true System.out.println(s4 == s4.intern()); // is false System.out.println(s1 == "abc"); // is true System.out.println(s1 == new String("abc")); // is false 。为了进行比较,实习字符串可能比您想象的要慢,并且不必要地填充哈希表。特别是对于内容差异很大的字符串。

  1. s3是来自常量池的字符串文字,因此被实习。 s4是不产生实体常数的表达式。
  2. 当你实习生s4时,它与s3具有相同的内容,因此是同一个实例。
  3. 与s4相同,表达式不是常数
  4. 如果你实习s1 + s2你得到s3的实例,但s4仍然不是s3
  5. 如果你是实习生s4,它与s3
  6. 是同一个实例

    还有一些问题:

    "a" + "bc"

    *编译时常量可以是在连接两边都有文字的表达式(如 final String a = "a"; final String b = "b"; final String ab = a + b; final String ab2 = "a" + b; final String ab3 = "a" + new String("b"); System.out.println("ab == ab2 should be true: " + (ab == ab2)); System.out.println("a+b == ab should be true: " + (a+b == ab)); System.out.println("ab == ab3 should be false: " + (ab == ab3)); ),也可以是从常量或文字初始化的最终字符串变量:

    view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);

答案 1 :(得分:0)

您必须知道的一件事是,Strings是Java中的对象。变量s1-s4不直接指向您存储的文本。它只是一个指针,指示在RAM中找到文本的位置。

  1. 这是错误的,因为您比较指针,而不是实际文本。文本是相同的,但这两个字符串是2个完全不同的对象,这意味着它们有不同的指针。尝试在控制台上打印s1和s2,您将看到。

  2. 这是真的,因为Java对字符串进行了一些优化。如果JVM检测到两个不同的字符串共享相同的文本,它们将被称为“字符串文字池”。由于s3和s4共享相同的文本,因此它们也会在“String Literal Pool”中使用相同的插槽。 inter() - Method获取对Literal Pool中String的引用。

  3. 与1.相比,你比较两个指针。不是文字内容。

  4. 据我所知,添加的值不会存储在池中

  5. 与2.相同。它们包含相同的文本,因此它们存储在String Literal Pool中,因此共享相同的插槽。

答案 2 :(得分:0)

首先,s1,s2和s3在声明它们时在实习池中,因为它们是由文字声明的。 s4不在实习池中开始。这就是实习池可能看起来的样子:

$(document.body).on('click','*:not(.edit-btn, .save-btn, .tabs, #edit-wrapper)', function(){
    YOUR CODE
});
  1. s4与s3不匹配,因为s3在实习池中,但s4不在。
  2. intern()在s4上调用,因此它在池中查找等于“abcabc”的其他字符串并使它们成为一个对象。因此,s3和s4.intern()指向同一个对象。
  3. 同样,在添加两个字符串时不会调用intern(),因此它与intern()池不匹配。
  4. s4不在实习池中,因此它与(s1 + s2).intern()的对象不匹配。
  5. 这些都是实习生,所以他们都看实习生池并找到对方。