==和equals()方法都可以判断是否相等,那么二者有何区别?
==用于基本数据类型之间的比较,当比较引用对象时,比较的是否引用到堆上的同一个对象。
equals()判断两个对象是否存在意义上相等。相等的意义要看对象的类型来判断,比如两个不同的String带有相同的字符,这样可以认为是相等的;但对Dog对象来说,age和name一样的,未必就是一样。
equals()方法是基于Object类的,而通过源码发现equals()方法底层依赖的是==号,也就是说在没有重写equals()方法的类中,调用equals()方法的效果和==是一样的,也是比较的是地址值。
public boolean equals(Object obj) { return (this == obj); }
创建一个Book类用于测试说明==和equals的区别
/** * 创建一个Book类用于测试说明==和equals */ class Book{ public Book(){ } public Book(int size,double price,String name){ this.size = size; this.price = price; this.name = name; } private int size; private double price; private String name; public int getSize() { return size; } public void setSize(int size) { this.size = size; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
创建测试类进行测试
@Test public void testEqual(){ Book c = new Book(1,2.0,"Java"); Book d = new Book(1,2.0,"Java"); Book e = d;
//size,price都属于基本数据类型,没有equals()方法,故比较时采用== System.out.println(c.getSize() == d.getSize());//true System.out.println(c.getPrice() == d.getPrice());//true System.out.println(c.getName().equals(d.getName()));//true System.out.println(c == d);//false; System.out.println(c == e);//false System.out.println(e == d);//true System.out.println(e.equals(d));//true System.out.println(c.equals(d));//false }
再来看一个例子
String str1 = new String("aaa"); String str2 = new String("aaa"); System.out.println(str1.equals(str2));//true System.out.println(str1 == str2);//false
这个例子equals()方法返回true,==返回false,初看之下或许会觉得和我们上面讲的有矛盾,其实不然,String类中重写了equals()方法,所以会返回true。看一下String类中的equals()方法源码
private final char value[];
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
还有最后一个例子
String s1 = "abc"; String s2 = "abc"; System.out.println(s1.equals(s2));//true System.out.println(s1 == s2);//true
我们说了对于引用类型比较的是两个地址是否相等,那么为什么两个都是true?这涉及到常量池,当创建s1是,常量池中如果没有,那么就会创建一个"abc",当创建s2时,并不会重新创建而是直接使用该常量。
String str1 = new String("aaa"); 中创建了两次对象,首先在常量池中创建了"aaa",然后在堆内存中又开辟一块str1。所以str1和str2的地址不等,而s1和s2的地址是相等的。