【问题标题】:Java: Why can String equality be proven with ==?Java:为什么可以用 == 证明字符串相等?
【发布时间】:2010-12-23 22:25:10
【问题描述】:

我知道用==而不是String.equals()来测试String是否相等是魔鬼,因为每个String都是对其自身对象的引用。

但是如果我使用类似的东西

System.out.println("Hello" == "Hello");

它打印的是真的。

为什么?

【问题讨论】:

  • 看看stackoverflow.com/questions/1091045/…。他们也讨论了这个问题。
  • 请发布一个示例,说明“现在如何工作”。
  • 这很有趣 - 我正在反转 {string == null ? "" : string} - 我的所有测试都通过了,但是当开始从数据库中读取字符串时...

标签: java string


【解决方案1】:

它没有。这仍然是一件坏事 - 您仍将测试引用相等性而不是值相等性。

public class Test
{
    public static void main(String[] args)
    {
        String x = "hello";
        String y = new String(x);
        System.out.println(x == y); // Prints false
    }
}

如果您现在看到 == 测试“工作”,那是因为您确实拥有平等的参考。看到这种情况的最常见原因可能是由于 String 字面量的实习,但这一直存在于 Java 中:

public class Test
{
    public static void main(String[] args)
    {
        String x = "hello";
        String y = "hel" + "lo"; // Concatenated at compile-time
        System.out.println(x == y); // Prints true
    }
}

这是由 Java 语言规范的 section 3.10.5 保证的:

每个字符串字面量都是一个引用 (§4.3) 到一个实例 (§4.3.1, §12.5) 类字符串(§4.3.3)。细绳 对象具有恒定值。细绳 文字,或者更一般地说,字符串 这是常量的值 表达式(第 15.28 节)- 被“实习”所以 至于共享独特的实例,使用 String.intern 方法。

【讨论】:

  • 谢谢 - 但是如果我使用两个相同的文字,为什么它会起作用?
【解决方案2】:

它没有改变。但是,Java 编译器使用 string.intern() 来确保源代码中的相同字符串编译为相同的 String 对象。但是,如果您从文件或数据库加载字符串,它将不是同一个对象,除非您使用 String.intern() 或其他方法强制执行此操作。

这是个坏主意,你还是应该使用 .equals()

【讨论】:

  • 手动实习 String 对象是有风险的,因为它们永远不会被取消实习或垃圾收集。以这种方式可以轻松消耗所有可用内存。
  • @Adriaan - 无法访问的实习字符串被垃圾收集。这显然是在 JDK 1.2 中实现的。
【解决方案3】:

看,这是一个棘手的概念。

两者之间有区别:

// These are String literals
String a = "Hiabc";
String b = "abc";
String c = "abc";

// These are String objects.
String a = new String("Hiabc");
String b = new String("abc");
String c = new String("abc"); 

如果你的字符串是对象,即

String b = new String("abc");
String c = new String("abc");

然后,两个不同的对象将在字符串池中的两个不同内存位置创建并执行

b == c  

会产生false

但由于您的 String bString c 是文字,

b == c  

结果true。这是因为没有创建两个不同的对象。 ab 都指向堆栈内存中的相同字符串。

这就是区别。你是对的,== 比较内存位置。这就是原因,

a.substring(2, 5) == b; // a,substring(2, 5) = "abc" which is at the location of b, and
b == c // will be true, coz both b and c are literals. And their values are compared and not memory locations.

为了在String poolNOT stack memory 中拥有两个具有相同值但位于不同位置的单独字符串,您需要创建如上所示的字符串对象。

所以,

a.substring(2, 5) == b; // and
b == c; // will be false. as not both are objects. Hence are stored on separate memory locations on the String pool.

你必须使用

a.substring(2, 5).equals(b);
b.equals(c);

如果是对象。

【讨论】:

    猜你喜欢
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 2019-05-20
    相关资源
    最近更新 更多