理解在c#和Java中产生不同结果的字符串的显式转换
我为Java7和C#(.NET3.5)编写了一段相同的(…类似的?)代码,得到了一个令人困惑的输出。请帮助我理解这种行为: 爪哇: 输出:false 假的 真的 C#: 输出:真 假的 真的 我知道诸如字符串不变性和字符串池之类的概念,但我想我错过了更详细的内容理解在c#和Java中产生不同结果的字符串的显式转换,c#,java,C#,Java,我为Java7和C#(.NET3.5)编写了一段相同的(…类似的?)代码,得到了一个令人困惑的输出。请帮助我理解这种行为: 爪哇: 输出:false 假的 真的 C#: 输出:真 假的 真的 我知道诸如字符串不变性和字符串池之类的概念,但我想我错过了更详细的内容 在java中:当s2可以使用s1引用的字符串对象时,为什么它要为s2创建一个新的字符串对象?这不是字符串池应该实现的吗?您的问题有两个方面:对象是何时创建的,以及比较是如何工作的: 对象创建 就内部(“池”)而言,只有常量会自动内部。您
在java中:当s2可以使用s1引用的字符串对象时,为什么它要为s2创建一个新的字符串对象?这不是字符串池应该实现的吗?您的问题有两个方面:对象是何时创建的,以及比较是如何工作的: 对象创建 就内部(“池”)而言,只有常量会自动内部。您可以使用
intern
/intern
插入其他字符串,但只要调用字符串构造函数,就会始终创建一个新字符串。(好吧,除了.NET中的一个奇怪的角落案例,但我们现在可以忽略它。)
因此,在代码中,s1
和s2
总是指不同的对象
比较
造成差异的原因是您使用了==
。C#支持用户定义的运算符重载,并且String
将其重载如下:
public static bool operator ==(string x, string y)
它比较字符串的内容而不是引用。因此,当您有两个string
类型的操作数时,x==y
将执行相等比较,而不是身份比较。这就是为什么C输出的第一行是True
Java没有这种行为,这就是为什么打印false
当操作数类型为Object时,C#和Java都将使用引用相等,这就是为什么第二行在这两种情况下都为false。我假设您在问为什么C#表示s1==s2?字符串比较以区分大小写的方式比较两个字符串的内容。由于两个字符串具有相同的内容,因此它们的比较返回true 在Java中,只比较字符串引用,以确定两个变量是否引用同一个字符串。它们的内容没有进行比较
至于池,Java和C都对文本使用池(在C中实习)。以编程方式创建的字符串会产生两种语言的新实例,即使池实例已经存在。检查的documantation以获得与您类似的示例,其中插入的字符串与生成的字符串是不同的实例,即使它们的值相同。字符串池仅用于文本。
如果您说String s1=“abc”;字符串s2=“abc”;将只创建一个对象。java语言规范要求,当您使用“new”关键字时,将创建一个实际的新对象,并且不会欺骗和返回内部缓存副本
Interning应用于以文字表示的字符串,但当您明确使用新关键字时,该语言必须使您成为一个实际的新的、不同的对象。请阅读格式帮助以了解未来的问题,在发布之前,使用预览查看您的问题的外观。出于好奇:C是否有一个
==
操作符来返回到=
的标准含义,或者对对象的强制转换是唯一的方法?@JBNizet:始终存在静态对象。ReferenceEquals(对象a、对象b)代码>。在我看来,这样做的目的比施放更清楚。@JBNizet:不,没有这样的操作员——正如linac所说,只要打电话给ReferenceEquals
@JonSkeet谢谢你的回答。只是出于好奇,是角盒->新字符串(新字符[0])?@PankajKohli:是的,就是这个。这很奇怪。不确定它是否真的在问题上下文中,但是+1让我在Java中发现了这一点。@Michael,谢谢,就在文章的末尾。他问为什么s1和s2有两个对象。
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
}
}
}
public static bool operator ==(string x, string y)