1.对象比较equals方法
如果==左右两侧是基本数据类型变量,比较的是变量中值是否相同
如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同。
如果一定要比较对象里面的内容的话,那么就需要重写Object中的equals方法,因为equals默认也是按照地址进行比较的。
// Object类中的equals方法
public boolean equals(Object obj) {
return (this == obj); // 使用引用中的地址直接来进行比较
}
上面是Object类中equals方法的具体实现,传入引用变量默认比较的是地址是否相同。
class Person{
private String name ;
private int age ;
public Person(String name, int age) {
// Person类重写equals方法后,然后比较:
// 结论:比较对象中内容是否相同的时候,一定要重写equals方法。
/*2.4 hashcode方法
回忆刚刚的toString方法的源码:
我们看到了hashCode()这个方法,他帮我算了一个具体的对象位置,这里面涉及数据结构,但是我们还没学数据结
构,没法讲述,所以我们只能说它是个内存地址。然后调用Integer.toHexString()方法,将这个地址以16进制输
出。*/
this.age = age ;
this.name = name ;
}
}
public class Test {
public static void main(String[] args) {
Person p1 = new Person("gaobo", 20) ;
Person p2 = new Person("gaobo", 20) ;
int a = 10;
int b = 10;
System.out.println(a == b); // 输出true
System.out.println(p1 == p2); // 输出false
System.out.println(p1.equals(p2)); // 输出false
}
}
上面的代码,Person类没有重写equals方法,所以导致new了两个对象,传入两个相同的参数,比较之后输出false;
public boolean equals(Object obj) {
if (obj == null) {
return false ;
}
if(this == obj) {
return true ;
}
// 不是Person类对象
if (!(obj instanceof Person)) {
return false ;
}
Person person = (Person) obj ; // 向下转型,比较属性值
return this.name.equals(person.name) && this.age==person.age ;
}
1.如果传入的对象为空值直接输出false
2.如果传入的是相等的引用变量 返回true
例如:Student student1 = new Student(); Student student2 = student1;
3.如果传入的不是与本类相同的类型 返会false
例如:student1.equals(dog)
4.因为传入的是Object类所以的需要向下转型到Person类,name是字符串比较,所以要调用equals方法进行比较,此时传入的是基本数据类型可以直接比较。this表示当前对象,person接收向下转型之后的参数引用。
public static void main(String[] args) {
// 验证两个对象相同的名字是否相等
Person student1 = new Person();
Person student2 = new Person();
student1.name = "1";
student2.name = "1";
System.out.println(student1.equals(student2));
}
运行main函数,使用student
比较两个传入相同参数的对象,输出的结果为相等。
2.hashcode方法
hashCode()这个方法,可以算一个具体的对象位置,这里面涉及数据结构,但是还没学数据结构,没法讲述,所以我们只能说它是个内存地址。然后调用Integer.toHexString()方法,将这个地址以16进制输出。
这部分后续进行补充。
该方法是一个native方法,底层是由C/C++代码写的。我们看不到。
我们认为两个名字相同,年龄相同的对象,将存储在同一个位置,如果不重写hashcode()方法,我们可以来看示例
代码:
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person per1 = new Person("gaobo", 20) ;
Person per2 = new Person("gaobo", 20) ;
System.out.println(per1.hashCode());
System.out.println(per2.hashCode());
}
}
//执行结果
460141958
1163157884
显然在没有重写hashcode()方法的前提之下,输出的哈希值是不同的。
像重写equals方法一样,我们也可以重写hashcode()方法。
步骤一:
步骤二
步骤三:选择你要重写方法传入的值(equals方法)
步骤四:选择你要重写方法传入的值(hashCode方法)
步骤五:创建
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name) && Objects.equals(m, student.m) && Objects.equals(H, student.H);
}
@Override
public int hashCode() {
return Objects.hash(name, age, m, H);
}
这里要保证传入你实例化类的参数都是一样的,才能输出相同的哈希值
上面的我只是传入了name的值
那么重写的时候我只加入name这个变量即可
@Override
public int hashCode() {
return Objects.hash(name);
}