我想澄清一下我的理解是否正确:
==是一个引用比较,即两个对象都指向相同的内存位置 .equals()计算为对象中值的比较
我想澄清一下我的理解是否正确:
==是一个引用比较,即两个对象都指向相同的内存位置 .equals()计算为对象中值的比较
当前回答
它是恒等和等价的区别。
A == b意味着A和b是相同的,也就是说,它们是内存中相同对象的符号。
A.equals (b)意味着它们是等价的,它们是在某种意义上具有相同值的对象的符号——尽管这些对象可能在内存中占据不同的位置。
注意,对于等价性,如何评估和比较对象的问题开始发挥作用——复杂的对象可能被认为是等效的,即使它们的一些内容不同。有了身份,就没有这样的问题了。
其他回答
根据你谈论的是“原语”还是“对象类型”,有一些小的区别;如果你在谈论“静态”或“非静态”成员,也可以这样说;你也可以混合上面所有的…
下面是一个例子(你可以运行它):
public final class MyEqualityTest
{
public static void main( String args[] )
{
String s1 = new String( "Test" );
String s2 = new String( "Test" );
System.out.println( "\n1 - PRIMITIVES ");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals( s2 )); // true
A a1 = new A();
A a2 = new A();
System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
System.out.println( a1 == a2 ); // false
System.out.println( a1.s == a2.s ); // true
System.out.println( a1.s.equals( a2.s ) ); // true
B b1 = new B();
B b2 = new B();
System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
System.out.println( b1 == b2 ); // false
System.out.println( b1.getS() == b2.getS() ); // false
System.out.println( b1.getS().equals( b2.getS() ) ); // true
}
}
final class A
{
// static
public static String s;
A()
{
this.s = new String( "aTest" );
}
}
final class B
{
private String s;
B()
{
this.s = new String( "aTest" );
}
public String getS()
{
return s;
}
}
您可以比较“==”(相等运算符)和“.equals(…)”的解释。(java.lang.Object类中的方法)通过以下链接:
= = http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html .equals(…):http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html # = (java . lang . object)
只需记住.equals(…)必须由您试图比较的类实现。否则,就没有什么意义了;Object类的方法版本所做的事情与比较操作相同:
唯一需要对对象使用比较运算符的时候是比较枚举的时候。这是因为一次只有一个Enum值的实例。例如,给定枚举
enum FooEnum {A, B, C}
你永远不会同时拥有一个以上的A实例,对于B和c也是如此。这意味着你实际上可以像这样编写一个方法:
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
你就不会有任何问题了。
下面是关系运算符==和方法.equals()之间区别的一般规则。
object1 == object2比较object1和object2引用的对象是否指向Heap中的相同内存位置。
object1.equals(object2)比较object1和object2的值,而不管它们位于内存中的哪个位置。
可以使用String很好地演示这一点
场景1
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? false
is str1.equals(str2) ? true
场景2
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? true
is str1.equals(str2) ? true
这种字符串比较可以用作比较其他类型对象的基础。
例如,如果我有一个Person类,我需要定义比较两个Person的标准。假设person类有身高和体重的实例变量。
因此,创建person对象person1和person2,并使用.equals()来比较这两个对象,我需要重写person类的equals方法,以定义基于哪个实例变量(高度或重量)的比较。
但是,==操作符仍然会根据两个对象(person1和person2)的内存位置返回结果。
为了便于泛化这个人对象比较,我创建了以下测试类。对这些概念进行实验会发现大量的事实。
package com.tadtab.CS5044;
public class Person {
private double height;
private double weight;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(height);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
/**
* This method uses the height as a means of comparing person objects.
* NOTE: weight is not part of the comparison criteria
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
return false;
return true;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.setHeight(5.50);
person1.setWeight(140.00);
Person person2 = new Person();
person2.setHeight(5.70);
person2.setWeight(160.00);
Person person3 = new Person();
person3 = person2;
Person person4 = new Person();
person4.setHeight(5.70);
Person person5 = new Person();
person5.setWeight(160.00);
System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
System.out.println("is person2 == person3 ? " + (person2 == person3)); // true
//this is because perosn3 and person to refer to the one person object in memory. They are aliases;
System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
// even if the person2 and person5 have the same weight, they are not equal.
// it is because their height is different
System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}
}
这个类执行的结果是:
is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
在计算代码时,很明显(==)是根据内存地址进行比较,而equals(Object o)是比较实例的hashCode()。 这就是为什么如果以后不遇到意外,就不要破坏equals()和hashCode()之间的契约。
String s1 = new String("Ali");
String s2 = new String("Veli");
String s3 = new String("Ali");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println("(s1==s2):" + (s1 == s2));
System.out.println("(s1==s3):" + (s1 == s3));
System.out.println("s1.equals(s2):" + (s1.equals(s2)));
System.out.println("s1.equal(s3):" + (s1.equals(s3)));
/*Output
96670
3615852
96670
(s1==s2):false
(s1==s3):false
s1.equals(s2):false
s1.equal(s3):true
*/
基本上,==比较两个对象在堆上是否有相同的引用,因此,除非两个引用链接到同一个对象,否则这种比较将为假。
equals()是继承自Object类的方法。默认情况下,如果两个对象具有相同的引用,则此方法进行比较。它的意思是:
object1.equals(object2) <=> object1 == object2
但是,如果您希望在同一类的两个对象之间建立相等性,则应该重写此方法。如果已经重写了equals(),重写hashCode()方法也是非常重要的。
当建立平等是Java对象契约的一部分时,实现hashCode()。如果你正在使用集合,并且你还没有实现hashCode(),可能会发生奇怪的糟糕事情:
HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));
如果您没有实现hashCode(),则在执行前面的代码后将打印null。