==
-
引用类型:== 是直接比较的两个对象的堆内存地址,如果相等,则说明两个引用实际是指向同一个对象地址的。
-
基本类型:对于 基本数据类型(8个)和 String 来说又是怎样呢?
int a = 123; int b = 123; System.out.println(a == b); // true String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // true String s3 = new String("abc"); System.out.println(s1 == s3); // false 复制代码
对于基本类型(8个)和 直接声明的 "abc" 字符串,他们是作为字面量存在常量池中以 HashSet 策略存储起来的,在常量池中,一个常量只会对应一个地址,所以它们的引用都是指向的同一块地址。
-
另外,对于基本数据的包装类型,除了Float和Double之外,其他的六种都是实现了常量池技术,其中 Integer 在常量池中的存储范围为 [-128,127] ,在这个范围外的值,会在堆内存中创建一个新的对象保存这个值。
equals
-
Object 的通用方法,在没有重写之前,与 == 是没有区别的;
public boolean equals(Object obj) { return (this == obj); } 复制代码
-
而一般 equals 方法是需要我们自行重写的,String 和 基本类型封装类就重写了 equals,从而进行的是内容的比较;
-
一般实现:
-
public class Student { private String num; private String name; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return Objects.equals(num, student.num) && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(num, name); } } 复制代码
-
检查是否为同一个对象的引用,如果是直接返回 true;
-
检查是否为空,是否同一类型,为空 或 类型不一致,返回 false;
-
将 Object 对象转型;
-
判断每个属性的值是否相等
-
hashCode
- Object 的通用方法,hashcode是根据对象的内存地址经哈希算法得来的;
- hashCode 方法主要是为了给 HashMap、HashSet 等集合类使用的。
- 一些规定:
- 两个对象相等,hashcode一定相等
- 两个对象不等,hashcode不一定不等
- hashcode相等,两个对象不一定相等
- hashcode不等,两个对象一定不等
为什么重写 equals 方法一定要重写 hashCode 方法?
- 官方说法是:对象的equals方法被重写,那么对象的hashCode()也尽量重写;(主要看应用场景)
- equals 方法 和 hashCode 方法本身并没有紧密的联系,只是应用场景(如HashMap、HashSet等集合类的存取)使它们出现在了一起,才有了这句话;
- 哈希集合(如HashMap)要保证元素唯一性。key对象放入集合,先经过hash运算,得到index,找到数组对应位置,还要和此位置的对象进行比较(先用hash比较,后用equals方法),不一样就插入到后面形成链表,一样的话就不用插入了。重写了equals()方法,但不重写hashcode()方法,那可能两个相同的对象放入到了不同的位置,元素的唯一性就不存在了。(HashMap存入键值对的方式要复杂的多,这里只是简要说下)