我们一般使用equals都是为了比较对象的内容,而Object里面的equals方法却是比较对象的引用,如下:
public boolean equals(Object obj) { return (this == obj); }
所以当我们想要比较的是对象的内容时,需要重写equals方法,假设User类中有String name , int age 两个字段,用eclipse自动生成的equals方法写法如下:
public boolean equals(Object obj) { if (this == obj) return true; // 两者引用相等则是同一个对象故内容相等 if (obj == null) return false; if (getClass() != obj.getClass()) // 两者的类不相等,则内容不可能相等 return false; User other = (User) obj; // 将其向下转型 if (age != other.age) // 下面就是开始比较内容 return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }
一个测试用例
public class Test { public static void main(String[] args) { User user1 = new User(); User user2 = new User(); System.out.println(user1.equals(user2)); } }
打印true。如果把User类重写的equals方法去掉,此时user1.equals()调用的是Object类的equals方法,比较的是引用而不是内容,user1和user2的引用明显不同,故打印false。常用的equals方法比较的是对象的内容,即对象要属于同一个类且字段属性相等才相等。
HashCode主要用于类集框架。假设我们对一个类不重写hashCode方法,对象调用hashCode方法时则调用的是Object类的hashCode方法:
public native int hashCode();
生成的散列值都是不相同的,而如果我们重写了hashCode方法,对于内容相同的对象则可以生成相同的散列值。
至于hashCode方法写法,我们一般也不需要记住,直接用工具生成就好了。
测试用例:
public class Test { public static void main(String[] args) { // TODO 自动生成的方法存根 HashSet<User> set = new HashSet<>(); User user1 = new User("leelit", 21); User user2 = new User("leelit", 21); User user3 = new User(); System.out.println(user1.hashCode()); System.out.println(user2.hashCode()); System.out.println(user3.hashCode()); set.add(user1); // 添加user1和user2 set.add(user2); System.out.println(set.size()); HashMap<User, String> map = new HashMap<>(); map.put(new User("lina", 21), "value"); System.out.println(map.get(new User("lina", 21))); } }
打印结果:
-1106625705 -1106625705 961 1 value
把User类重写的hashCode方法去掉后打印:
31168322 17225372 5433634 2 null
没有重写hashCode方法时:两个对象即使内容相等,也生成不同的散列值,所以都可以add进set里面去,我们知道HashSet是不可以有重复的元素的,所以这就是为什么必须要重写hashCode的原因;同理对于HashMap虽然put和get的是同样的key,但由于散列值不同,而被视作了不同的key,所以无法取出来。
重写hashCode方法后,两个相等的对象会生成相同的散列值。
时间: 2024-10-13 06:22:11