2

我为 Java 7 和 C#(.net 3.5) 编写了一段相同的(..similar?)代码,得到了一个令人困惑的输出。请帮助我理解这种行为:

爪哇:

public class strTest {
    public static void main(String [] s) {      
        String s1 = "abc";
        String s2 = new String(new char[] {'a', 'b', 'c'});
        System.out.println(s1 == s2);                      // false
        System.out.println(((Object)s1) == ((Object)s2));  // false
        System.out.println(s1.equals(s2));                 // true
    }
}

输出:假假真

C#:

namespace ConsoleApplication1
{
    class Program2
    {
        static void Main(string[] args)
        {
            String s1 = "abc";
            String s2 = new String(new Char[] {'a', 'b', 'c'});
            Console.WriteLine(s1 == s2);                     // true
            Console.WriteLine(((Object)s1) == ((Object)s2)); // false
            Console.WriteLine(s1.Equals(s2));                // true
        }
    }
}

输出:真假真

我知道诸如字符串不变性和字符串池之类的概念,但我想我错过了更详细的说明。

在 java 中:为什么它可以使用 s1 引用的对象,但它会为 s2 创建一个新的 String 对象?这不是字符串池应该实现的吗?

4

4 回答 4

15

您的问题有两个方面:创建对象的时间以及==比较的工作方式:

对象创建

就实习(“池”)而言 - 只有常量会自动实习。Intern您可以使用/实习其他字符串intern,但是当您只调用将始终创建一个新字符串的字符串构造函数时。(嗯,除了 .NET 中的一个奇怪的极端情况,但我们现在可以忽略它。)

所以在你的代码中,s1总是s2引用不同的对象。

比较

造成差异的原因是您使用==. C# 支持用户定义的运算符重载,并String像这样重载它:

public static bool operator ==(string x, string y)

它比较字符串的内容而不是引用。因此,当您有两个类型的操作数时stringx == y最终会进行相等比较而不是身份比较。这就是为什么 C# 输出的第一行是True.

Java没有这种行为,这就是 prints 的原因false

当操作数类型为Object时,C# 和 Java 都将使用引用相等,这就是为什么第二行在两种情况下都是 false 的原因。

于 2012-06-21T07:22:01.293 回答
2

我假设您在问为什么 C# 说 s1==s2?字符串比较以区分大小写的方式比较两个字符串的内容。由于两个字符串具有相同的内容,因此它们的比较返回 true。

在 Java 中,仅比较字符串引用,以确定两个变量是否引用相同的字符串。它们的内容没有进行比较。

至于池化,Java 和 C# 都对文字使用池化(在 C# 中实习)。以编程方式创建的字符串会产生两种语言的新实例,即使已存在池化实例也是如此。检查String.Intern的文档以获取与您类似的示例,其中实习字符串与生成的字符串是不同的实例,即使它们的值相同。

于 2012-06-21T07:22:25.670 回答
1

字符串池仅用于文字。如果你说 String s1 = "abc"; 字符串 s2 = "abc"; 只会创建一个对象。

于 2012-06-21T07:23:59.483 回答
0

java 语言规范要求,当您使用“new”关键字时,会创建一个实际的新对象,不作弊并返回内部缓存副本。

当评估类实例创建表达式(第 15.9 节)导致类被实例化时,会显式创建一个新类实例。

实习应用于表示为文字的字符串,但是当您明确使用新关键字时,语言必须使您成为一个实际的新的、不同的对象。

于 2012-06-21T07:25:55.240 回答