使用字符串的==运算符 [英] == operator with Strings

查看:145
本文介绍了使用字符串的==运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码不应该打印Bye,因为==运算符用于比较引用,但奇怪的是,仍然会打印Bye。为什么会这样?我正在使用Netbeans 6.9.1作为IDE。

The code below should not print "Bye", since == operator is used to compare references, but oddly enough, "Bye" is still printed. Why does this happen? I'm using Netbeans 6.9.1 as the IDE.

public class Test {
    public static void main(String [] args) {
        String test ="Hi";
        if(test=="Hi"){
            System.out.println("Bye");
        }
    }
}


推荐答案

此行为是因为实习。该行为在 <$ c $的文档中有所描述。 c> String #intern (包括为什么它出现在您的代码中,即使您从未调用 String #intern ):

This behavior is because of interning. The behavior is described in the docs for String#intern (including why it's showing up in your code even though you never call String#intern):


字符串池(最初为空)由类 String 私有维护。

当调用实习生方法时,如果池已包含等于此的字符串字符串 equals(Object)方法确定的对象,然后返回池中的字符串。否则,将此 String 对象添加到池中,并返回对此 String 对象的引用。

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

对于任何两个字符串 s t s.intern()== t.intern() true 当且仅当 s时。 equals(t)为真。

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

所有文字字符串和字符串值常量表达式都是实体。字符串文字在 Java语言规范的§3.10.5中定义。

All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification.

例如:

public class Test {

    private String s1 = "Hi";

    public static void main(String [] args) {

        new Test().test();
        System.exit(0);
    }

    public void test() {
        String s2 ="Hi";
        String s3;

        System.out.println("[statics]          s2 == s1? " + (s2 == s1));
        s3 = "H" + part2();
        System.out.println("[before interning] s3 == s1? " + (s3 == s1));
        s3 = s3.intern();
        System.out.println("[after interning]  s3 == s1? " + (s3 == s1));
        System.exit(0);
    }

    protected String part2() {
        return "i";
    }
}

输出:

[statics]          s2 == s1? true
[before interning] s3 == s1? false
[after interning]  s3 == s1? true

走过:


  1. 分配给<的文字code> s1 会自动实习,因此 s1 最终会引用池中的字符串。

  2. 分配给 s2 的文字也是自动实习的,因此 s2 最终指向同一个实例 s1 指向。这很好,即使代码的两位代码可能彼此完全不知道,因为Java的 String 实例是不可变的。你无法改变它们。您可以使用 toLowerCase 之类的方法来获取带有更改的 new 字符串,但原来您调用 toLowerCase (等)保持不变。所以它们可以安全地在不相关的代码中共享。

  3. 我们通过运行时创建 new <$ c> c> String 实例操作。即使新实例与实际实例具有相同的字符序列,它也是单独的实例。运行时不会自动生成动态创建的字符串,因为涉及成本:在池中查找字符串的工作。 (编译时,编译器可以将成本转嫁给自己。)现在我们有两个实例,一个是 s1 s2 指向,并且 s3 指向。所以代码显示 s3!= s1

  4. 然后我们明确实习生 s3 。也许这是我们计划长期坚持的大字符串,我们认为它可能会在其他地方重复。因此,我们接受实习的工作,以换取潜在的内存节省。由于根据定义实习意味着我们可能会返回一个新的参考,我们将结果分配回 s3

  5. 我们可以看到实际上, s3 现在指向同一个实例 s1 s2 指向。

  1. The literal assigned to s1 is automatically interned, so s1 ends up referring to a string in the pool.
  2. The literal assigned to s2 is also auto-interned, and so s2 ends up pointing to the same instance s1 points to. This is fine even though the two bits of code may be completely unknown to each other, because Java's String instances are immutable. You can't change them. You can use methods like toLowerCase to get back a new string with changes, but the original you called toLowerCase (etc.) on remains unchanged. So they can safely be shared amongst unrelated code.
  3. We create a new String instance via a runtime operation. Even though the new instance has the same sequence of characters as the interned one, it's a separate instance. The runtime doesn't intern dynamically-created strings automatically, because there's a cost involved: The work of finding the string in the pool. (Whereas when compiling, the compiler can take that cost onto itself.) So now we have two instances, the one s1 and s2 point to, and the one s3 points to. So the code shows that s3 != s1.
  4. Then we explicitly intern s3. Perhaps it's a large string we're planning to hold onto for a long time, and we think it's likely that it's going to be duplicated in other places. So we accept the work of interning it in return for the potential memory savings. Since interning by definition means we may get back a new reference, we assign the result back to s3.
  5. And we can see that indeed, s3 now points to the same instance s1 and s2 point to.

这篇关于使用字符串的==运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆