我正在研究两者之间的差异,我注意到.equals似乎比==更可靠。是否有理由使用== over .equals而不是(我假设)速度增加?
我正在做这项研究,因为我在Java上做了一些工作。当您考虑其他语言(如C#或C ++)时,是否会有更重要的区别?如果是的话,你能告诉我为什么吗?
编辑:也许我应该澄清一下。当我说.equals更可靠时,我的意思是我无法想到.equals不适合的比较,但很容易想出你的情况应该避免==。任何人都可以向我提供一个相当具体的例子,说明您何时使用==,但不是 .equals?答案 0 :(得分:3)
比较Java中的String对象有很大的不同。使用equals()
将比较字符串的内容并告诉您结果。使用==
将比较对象并告诉您变量是否引用相同的对象。如果使用==
,则包含完全相同字符的两个字符串将显示为不相等,因为它们是不同的对象(即,您可以修改一个而另一个将保持不变)。使用==
来比较String
个对象是一个非常常见的错误。 equals()
是比较String
内容的正确方法。
答案 1 :(得分:2)
==检查参考相等性; .equals检查值的相等性。所以他们并没有真正检查同样的事情; ==正在测试两个东西是否是同一个对象,而.equals正在检查它们是否具有相同的值(这就是为什么必须为.equals定义一些操作并且可以被覆盖的原因)。
答案 2 :(得分:1)
嗯,有一些原始数据类型,其中.equals不受支持,因为所讨论的数据类型在技术上不是类(例如原始布尔值或整数)。
除此之外,正如您已经想到的那样 - 使用==与使用.equals相比时的性能差异。
话虽如此,除非你在.equals方法中,否则使用'=='代替.equals 通常是Java中的错误。 '=='检查引用的相等性(想想:指针的相等性,如果你来自C / C ++世界),和.equals调用一个equals方法,该方法具有由类的开发人员定义的语义。
答案 3 :(得分:1)
是的,有时间使用==
代替equals
方法。通常,相等方法检查类的通常输出。例如,包含单词“cat”的字符串,因此当您使用它所检查的相等方法时。然而,一个类不仅仅是一个字段,而是许多字段以及内存中的地址。在类上使用==
时,它会逐字检查它是否指向内存中的同一实例。只有原始类型==
才能完成您的想法。
这是一个非常酷的实验来证明...
String a = "123";
String b = "123";
编译器将字符串优化到同一地址,因此==将返回true。但是,在运行时更改b的值EVEN TO 123和==将返回false,因为现在它们在内存中有不同的地址,因为虚拟机不够智能或在运行时进行这些优化效率不高-time。
Scanner input = new Scanner(System.in);
b = input.nextLine();
即使输入123,也会导致==返回false,因为它现在在内存中创建了一个新点。
答案 4 :(得分:1)
我正在研究两者之间的差异,我注意到.equals似乎比==更可靠。
然后你的研究不充分和/或你对所读内容的理解是不正确的。
实际上,==
和equals
正在测试不同的内容。
obj == obj2
正在测试obj
和obj2
是否是同一个对象引用。
obj.equals(obj2)
正在测试obj
和obj2
是否等于obj
的定义/相等均值的概念。此可以与第一种情况相同。但它可能是完全不同的东西。它完全取决于equals
的{{1}}方法的实现方式... obj
。例如,equals
测试的 common 涉及比较各个对象的字段值。
为了说明,如果我使用==
来测试一对字符串,我实际上正在测试它们是否是相同的String
对象。但是如果我使用equals
,我实际上是在测试各个String
对象是否由相同顺序的相同字符组成。这是两个不同的测试,在很多情况下,他们会给出不同的答案。
是否有理由使用== over .equals而不是(我假设)速度增加?
是。他们意味着不同的东西。因此,您应该主要根据测试的预期含义在==
和equals
之间进行选择...在您正在执行此操作的上下文中。
任何人都可以向我提供一个相当具体的例子,说明你何时使用==,而不是.equals?
在您有可变对象的情况下可能会发生这种情况。有时您可能需要比较它们"按值"。其他时候你需要知道两个对象是否实际上是相同的。后者可能会在您遍历这些对象的图形时发生,并且您需要知道您是否已经过#34;。
问题在于,任何一个例子都会有点人为......在某种意义上它可能以其他方式实现(可以说是更好)。
答案 5 :(得分:1)
一个例子是IdentityHashMap,请参阅API
此类使用哈希表实现Map接口,在比较键(和值)时使用引用相等性代替对象相等性。换句话说,在IdentityHashMap中,当且仅当(k1 == k2)时,两个密钥k1和k2被认为是相等的。 (在正常的Map实现中(如HashMap),当且仅当(k1 == null?k2 == null:k1.equals(k2))时,两个键k1和k2被认为是相等的。)
答案 6 :(得分:0)
.equals()
并不可靠。它只是提供了一个非常不同但却被忽视的目的。如上所述,.equals()
比较值 - 而不是引用 - 并且在比较某些事物(如字符串)时很有用。我建议您使用==
而不是.equals()
,除非您知道明确需要.equals()
。这不仅是因为==
更快,而且因为它是常见的做法*。
*我有点担心称它为惯例,但这绝对是常见的做法
答案 7 :(得分:0)
正如其他人所说,==比较引用,而.equals比较值。 ==比.equals更快,但如果一个对象的多个实例可以具有相同的值并且您正在比较这些值,则不能使用==并期望它是正确的。如果两个对象是不同的实例,但具有相同的值,则==将返回false。
也就是说,有一些不可变对象实现"实例控制"。
他们使用静态工厂方法执行此操作。该类将定义一个静态Map,其中包含已创建的所有对象的实例。静态工厂方法将使用传递给它的参数实例化一个对象。但是,在返回对象之前,它会检查Map以查看它是否具有相同值的对象。
如果找到相同的值,则返回Map中具有相同值的对象而不是新创建的对象。
如果找不到相等的对象,它会将新创建的对象添加到Map并返回新对象。
这样做的好处是,对于实现实例控制的对象,使用==检查值是否相等是安全的,因为不可能存在具有相同值的两个对象。
Effective Java讨论了第2章中的实例控制。
Guava有一个名为Interners的类,通过在Interner结构中存储自身的对象,使得想要实现实例控制的类变得微不足道。
实现这样的实例控制的不可变对象应该表明它们在文档中执行。如果他们这样做,您就知道使用==检查值是否相等是安全的。但是,对于任何不实现实例控制的不可变对象,应始终使用.equals来检查值是否相等。