2014-04-16 37 views
1

我对这两者之间的差异做了一些研究,我发现.equals似乎比==更可靠。除了(我假设)速度增加之外,是否有理由使用==而非.equals?除了速度之外,是否有使用==而不是速度的理由?

我正在做这项研究,因为我正在与Java做一些工作。如果考虑其他语言,比如C#或C++,会不会在使用上有更重要的区别?如果是这样,你能告诉我为什么?

编辑:也许我应该澄清。当我说.equals更可靠时,我的意思是说我无法想象.equals不适合的比较,但很容易想出应该避免的情况==。任何人都可以提供一个相当具体的例子,当你使用==,但不是 .equals?

+1

?请相应地标记您的问题。 – Floris

+2

有一些罕见的情况(不能想象一个快速的例子,但是)你想确保有*完全相同的*对象与看起来相同的对象。字符串不太可能,对于其他类更可能。 –

+0

我的想法不正确。等于以多种语言存在? – Kulahan

回答

1

是的,有一段时间可以用==代替equals的方法。通常,相等方法检查类的正常输出。例如,包含单词“cat”的字符串,因此当您使用它检查的相等方法时。然而,一个类不仅仅是一个字段,还有许多字段以及内存中的地址。在类上使用==时,它会逐字检查它是否指向内存中的同一实例。只有原始类型==才能做你认为它的功能。

这是一个非常酷的实验来证明......

String a = "123"; 
String b = "123"; 

编译器优化串到相同的地址,因此==将返回true。但是,在运行时EVEN TO 123时更改b的值,并且==将返回false,因为现在它们在内存中具有不同的地址,因为虚拟机不够智能,或者在运行时进行这些优化效率不高-时间。

Scanner input = new Scanner(System.in); 
b = input.nextLine(); 

即使您输入123,它也会导致==返回false,因为现在它在内存中创建了一个新点。

3

比较Java中的String对象时有很大的区别。使用equals()将比较字符串的内容并告诉你结果。使用==将比较对象并告诉您变量是否引用同一对象。如果使用==那么包含完全相同字符的两个字符串将显示为不相等,因为它们是不同的对象(即,您可以修改一个而另一个将保持不变)。使用==来比较String对象是一个非常常见的错误。 equals()是比较String内容的正确方法。

+0

我想我有点理解这一开始,但感谢您的更多澄清。你有关于问题其余部分的任何信息吗?我很好奇你什么时候可以在Java中使用==。 – Kulahan

+0

通常如果一个类有一个'equals()'方法,你应该使用它。对于原始类型(int,boolean)或与'null'比较,您应该使用'=='。对于类,当你正在进行自省或其他类级别的工作时,使用'=='可能会很有用,因为如果您真的有兴趣了解两个变量是否引用同一个对象。 –

2

==检查引用是否相等; .equals检查值相等。所以他们没有真正检查同样的事情; ==测试两件事是否是同一个对象,并且.equals检查它们是否具有相同的值(这就是为什么某些操作必须为.equals定义,并且可以被覆盖)。

1

那么,有一些原始数据类型,其中.equals不会被支持,因为所讨论的数据类型在技术上不是类(例如原始布尔或整数)。

除此之外,在使用==时与使用.equals相比,存在 - 如您已经想到的那样 - 性能差异。

话虽如此,使用'=='而不是.equals是通常是 Java中的错误,除非您在.equals方法中。 '=='会检查引用的相等性(想想:如果您来自C/C++世界,指针是否相等),并且.equals会使用该类的开发人员定义的语义调用equals方法。

1

我对这两者之间的区别做了一点研究,我注意到.equals似乎简单地比==更可靠。

那么你的研究是不够的和/或您的您已经阅读理解是不正确。

实际上,==equals正在测试不同的东西。

  • obj == obj2正在测试objobj2是否相同对象引用。

  • obj.equals(obj2)正在测试objobj2是否是根据什么平等意味着obj的定义/概念等号。这可能与第一种情况相同。但它可能是完全不同的东西。这完全取决于如何实施equals方法......对于obj。例如,对于equals测试,它是通用,以涉及比较各个对象的字段的值。

为了说明这一点,如果我使用==测试一对字符串,我实际测试,看看他们是相同的String对象。但是如果我使用equals,我实际上正在测试以查看各个String对象是否由相同顺序的相同字符组成。这是两种不同的测试,在很多情况下,他们会给出不同的答案。

是否有理由使用==而不是(我假设)速度增加.equals?

是的。他们的意思是不同的东西。所以你应该主要是根据测试的预期含义在上下文中选择==equals

任何人都可以提供一个相当具体的例子,当你使用==,但不是.equals?

它可能发生在你有可变对象的情况下。有时你可能需要“按价值”比较它们。其他时候,您需要知道两个对象是否实际相同。当你遍历这些对象的图形时,后者可能会发生,并且你需要知道你是否“在此之前”。

问题是,任何示例都会有点虚构......因为它可能可以通过其他方式实现(可以说是更好)。

+0

只有一个虚拟'equals' /'hashCode'对是很糟糕的,因为等价性取决于一个对象是否会改变,对象的持有者通常会比对象本身更了解这个对象。只有一个方法对只会等同于那些总是等价的东西,而另一个方法对将被认为是相同的东西,除非等到其中一个方法被修改,否则这些方法对可以做很多工作来解决这些问题。 – supercat

1

一个例子是IdentityHashMap,见API

此类实现利用哈希表Map接口,比较键(和值)时使用引用相等代替对象相等的。换句话说,在IdentityHashMap中,当且仅当(k1 == k2)时,两个密钥k1和k2被认为是相等的。 (在正常Map实现(如HashMap的)两个键k1和k2被认为是相等的,当且仅当(K1 == NULL K2 == NULL:?k1.equals(K2)))

0

.equals()不据我所知,更可靠。它只是提供了一个非常不同但却被忽视的目的。如上所述,.equals()会比较值(而非引用),并且在比较某些内容(如字符串)时非常有用。除非您知道明确需要.equals(),否则我会建议使用==而不是.equals()。这不仅是因为==更快,而且因为它是常见的做法*。

*我是有点担心调用它约定的,但它肯定常例

0

正如其他人所说,==而.equals比较值进行比较引用。 ==比.equals更快,但是如果一个对象的多个实例可以具有相同的值并且您正在比较这些值,则不能使用==并且期望它是正确的。如果两个对象是不同的实例,但具有相同的值,则==将返回false。

这就是说,有一些不可变对象实现“实例控制”。

他们使用静态工厂方法执行此操作。该类将定义已创建的所有对象的实例的静态地图。静态工厂方法将使用传递给它的参数实例化一个对象。但是,在返回对象之前,它会检查Map以查看它是否具有相同值的对象。

如果找到一个相等,则返回具有相同价值的新创建的对象,而不是地图的对象。

如果它没有找到一个对象,它是平等的,它增加了新创建的对象的地图和返回新对象。

这样做的好处是,对于实现例如控制对象,它是安全的使用==检查值相等,因为没有办法具有相同值的两个物体将永远存在。

Effective Java讨论第二章实例控制2

Guava有类调用Interners使得它琐碎对于希望实现例如控制通过存储在Interner本身构造的对象这样做的一类。

像这样实现实例控制的不可变对象应该表明它们在文档中执行。如果他们这样做,你知道使用==来检查值是否平等是安全的。但是,对于不实现实例控制的任何不可变对象,应始终使用.equals来检查值是否相等。 '.equals`存在于哪种语言中?

相关问题