首先来说这是一个老问题,也是一个很基本的知识点,在面试的过程中我看到甚至有三年多工作经验的人说出的答案都很不专业,
以下是我个人的见解:
一.equals()方法的出处
在java的超类Object中是这么定义equals()方法的
public boolean equals(Object obj) { return (this == obj); } 通过源码我们可以清楚的看到返回的是 return (this == obj); 现在我们要搞清楚这个比较运算符"==" 这个"=="要从三方面来说: 1.在基本类型中比较的是值 基本类型中没有equals()方法, 值相同及相等 2.在基本类型包装类中严格来说比较的是内存地址 八种基本类型的包装类和对象池 java中基本类型的包装类的大部分都实现了常量池技术, 这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。 另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用常量池, 也即对象不负责创建和管理大于127的这些类的对象。 Integer i1 = new Integer(127); Integer i2 = new Integer(127); System.out.println(i1 == i2);// false Integer i11 = new Integer(128); Integer i22 = new Integer(128); System.out.println(i11 == i22);// falseInteger i5 = 127; Integer i6 = 127; System.out.println(i5 == i6);// true
//值大于127时,不会从常量池中取对象,指向的就是不同的引用
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);// false
3.在引用类型中比较的是内存地址
1).在String类中比较的是内存地址
String a = "abcd";
String b = "abcd";
String c = new String("abcd");
String d = new String("abcd");
System.out.println(a==b);//true
System.out.println(a=="abcd");//true
System.out.println(b=="abcd");//truea和b的值在字符串常量池中,因为a和b的值相同,在常量池中保存一份用一个引用标识,所以a和b在栈中指向字符串常量池中的同一个引用System.out.println(c==d);//false 用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()创建的字符串不放入常量池中,他们有自己的地址空间 c和d 分别在堆中存放两个不同的引用,图例:
2).在对象中比较的是内存地址(对象中未重写hscode())
Person p = new Person("华安", 23);
Person p2 = new Person("华安", 23);
System.out.println(p);// Person@33abb81e
System.out.println(p2);// Person@4ec4d412
System.out.println(p == p2);// false,比较的是内存地址
二.equals()方法在对象中使用(类中未重写hscode()和equals())
比较其对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象
三.equals()方法在String类中
String类中equals()方法是从它的超类Object中继承的,
被用来检测两个对象是否相等,即两个对象的内容是否相等,区分大小写。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; }四.equals()方法在基本类型包装类中
Integer类中重写了超类的equals()方法:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);// false
System.out.println(i1.equals(i2));// true
Integer i11 = new Integer(128);
Integer i22 = new Integer(128);
System.out.println(i11 == i22);// false
System.out.println(i11.equals(i22));// true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);//false
System.out.println(i3.equals(i4)); // true
Integer i5 = 127;
Integer i6 = 127;
System.out.println(i5 == i6);// true
System.out.println(i5.equals(i6)); //true
比较的是值;
小结:1.在对象中当类中没有重写equals()方法和hscode()方法时,equals()和==比较的是内存地址,比较是否是同一个对象
2.在String类中和基本类型包装类中equals()方法比较的是值,==比较的是内存地址。
3.在基本类型中没有equals()方法,==比较的是值。