摘自微信公众号:https://mp.weixin.qq.com/s?__biz=MzU1NTg0MzMwMg==&mid=2247483752&idx=1&sn=5018d012dc4423cccba18bb6785168a4&chksm=fbcf6ae1ccb8e3f7f6aa794f3d176fe3668c9ef404fff5d1c8d7555d50abcbfdd2648939ec13&token=1247180584&lang=zh_CN#rd
在java中比较两个对象(包括值,new出来的对象)是否相等,最常用的就是==和equals。大家比较糊涂这两个到底有什么区别,该怎么使用。
我们知道,java中的对象类型有2种,基本数据类型和引用数据类型,基本数据类型没问题,比较值就好了,因为基本数据类型的值就存放在变量中,也不存在equals方法。
当比较的对象是引用数据类型的时候,大家才会有这个问题。
==关系运算符
String str = new String("11");
首先我们知道,java的变量是申明在栈中的,对象是创建在堆中的,如果一个变量str引用一个对象,那么这个变量里面存的就是这个对象的地址值(这里不考虑对象因为GC而导致位置重排)。不同的对象,地址一定不同,只有同一个对象,地址才会相同。
比如:
String str1 = new String("11");
String str2 = new String("11");
System.out.print(str1==str2)
这时是false,因为new的对象都是在堆中的新对象。
但是
String str1 = "11";
String str2 = "11";
System.out.print(str1==str2)
这时是true,因为"11"会被java放进常量池中,被重复引用,而并没有创建新的对象。
equals()方法
很显然这是对象的方法。如果没有子类重写的话,默认调的总是Object类的equals方法,因为在java里面所有的类都继承自Object,不需要声明出来,所以所有的对象都会有equals方法。
public boolean equals(Object obj) {
return (this == obj);
}
这是Object中的方法返回的,默认就是使用的==关系运算符,就是比较两个对象的地址,换句话说就是看他们是不是同一个对象,并不关系对象的内容。而我们在业务中关系的是对象的内容是否相同,而不关系他们是不是同一个对象。
在默认情况下,==和equals是相同的,都是看两个对象地址是不是相同,即是不是同一个对象。
如果想比较对象的内容,就需要重写equals方法,因为==运算符我们拿他没办法。我们看看String是怎么重写equals方法的
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; }
他是拿到这2个字符串的字符数组,然后挨个去比较字符是不是相等,有一个字符不相等就返回false。所以字符串的equals是被重写了的equals,不再是Object的equals方法了。所以我们想比较啥,就把这个方法写成啥。
我们自己实现一下:
public class Student { private String a; private String b; public Student(String a, String b) { this.a = a; this.b = b; } }
public static void main(String[] args) { Student student1 = new Student("1", "2"); Student student2 = new Student("1", "2"); System.out.println(student1 == student2); System.out.println(student1.equals(student2)); }
输出的是false,false,因为这2个不是同一个对象
我们在Student中重写equals方法
public class Student { private String a; private String b; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public Student(String a, String b) { this.a = a; this.b = b; } public boolean equals(Object o) { Student s = (Student) o; return s.getA().equals(this.a)
&& s.getB().equals(this.b); } }
public static void main(String[] args) { Student student1 = new Student("1", "2"); Student student2 = new Student("1", "2"); System.out.println(student1 == student2); System.out.println(student1.equals(student2)); }
输出是false,true。重写了equals就会覆盖父类Object的equals方法,调的时候就会调子类的。
总之,==就是看是不是同一个对象,equals()就是调equals()方法,方法怎么写,就是怎么着。
摘自微信公众号