当前位置: 首页 > 知识库问答 >
问题:

混淆字符串引用比较==与实习生

郎经纶
2023-03-14

我读了这篇文章,当我们应该在字符串常量上使用字符串的实习生方法时,但仍然不太清楚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个答案

衡泰
2023-03-14

首先,s1、s2和s3在声明时都在intern池中,因为它们是由一个文本声明的。s4不在实习生池中。这就是实习生人才库的起点:

"abc" (s1, s2)
"abcabc" (s3)
  1. s4与s3不匹配,因为s3在实习生池中,但s4不在实习生池中
  2. 在s4上调用intern(),因此它会在池中查找其他等于“abcabc”的字符串,并将其作为一个对象。因此,s3和s4。intern()指向同一对象
  3. 同样,添加两个字符串时不会调用intern(),因此它与intern()池中的不匹配
  4. s4不在实习生池中,因此它不匹配对象(s1 s2)。实习生()
  5. 他们都是实习生,所以他们都在实习生池中寻找对方
濮嘉茂
2023-03-14

您必须知道的一件事是,字符串是Java中的对象。变量s1-s4不直接指向存储的文本。它只是一个指示在RAM中的何处查找文本的指针。

>

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

    这是真的,因为Java对字符串进行了一些优化。如果JVM检测到两个不同的字符串共享相同的文本,它们将只是在称为“字符串文字池”的东西中。由于s3和s4共享相同的文本,它们也将在“字符串文字池”中保存相同的槽。inter()-method获取对文字池中字符串的引用。

    与1相同。您比较两个指针。不是文本内容。

    据我所知,附加值不会存储在池中

    与2相同。它们包含相同的文本,因此它们存储在字符串文字池中,因此共享相同的插槽。

  • 沈英勋
    2023-03-14

    这里有相当多的答案来解释这个问题,但是让我给你另一个答案。

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

    首先:永远不要使用它。如果你不理解它,就不应该使用它。使用<代码>。等于()。为了比较而暂存字符串可能比您想象的要慢,并且不必要地填充哈希表。特别是对于具有高度不同内容的字符串。

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

    还有一些问题:

    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
    

    *编译时常量可以是在串联的两侧都有文本的表达式(如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));
    
     类似资料:
    • 我试图理解String#intern方法。现在,这引起了更多的混乱。 上面的代码打印为true。如果我注释第3行并取消注释第5行,则打印为false 对于第3行,将检查SCP,并将字符串添加到SCP中。但在这种情况下,s2如何等于s4呢 s2仍在引用堆中指向SCP常量的对象。正当 有人能解释一下发生了什么吗?我已经经历了不同的SO问题,但仍然无法理解。 EDIT 我只是想了解实习生方法。我知道b/

    • 问题内容: 在继续之前: 我知道我们应该使用.equals()比较内容。 我现在只是在谈论以下情况下的实际引用是否相同… 说我们有以下内容: 我认为应该是正确的,因为在字符串池中,对“字符串”的引用应该与str1和str2相同,现在都是“字符串”。它应该为true,但最终为 false 。 我尝试过,这次返回了 true 。然后我尝试了: 同样是 System.out.println(“ str”

    • 问题内容: 我对分配给False,True的测试值感到困惑 要检查真实值,我们只需 假怎么样? 问题答案: 从Python样式指南中: 对于序列(字符串,列表,元组),请使用空序列为假的事实。 [..] 不要使用==将布尔值与True或False进行比较。

    • 我当时在做一个计算机科学测试,并尝试了这个问题。 据我所知,我认为打印输出是假的,因为据我所知,字符串只能与。等于()。但我弄错了。它说答案是假的,是真的。有人能解释一下原因吗?

    • 我们正在使用dexguard,并且在dexguard项目中还具有以下设置。文本 我还尝试了提供res/值/字符串的变体。类似xml的: 和 等 在小路上。但字符串的键值正在变得模糊。 正在返回0。(其中key是字符串值)。 我也试过了 避免字符串OBF指令的正确方法是什么?

    • 我是一名自学型开发人员,现在正在学习Java。我了解到,要对函数接口使用方法引用,我们引用的方法的签名必须与该函数接口内抽象方法的签名匹配。 但是在学习比较器时,发现“Comparator.comparing()”方法接受函数接口并返回一个比较器。我知道函数接口的抽象方法必须接受一个参数并返回一个值。 但是我可以将任何部分(而不是完全)匹配Function接口签名的方法(作为方法参考)传递给比较器