java中利用assert判断两个数组是否相同_Java基础:详解equals

df796744077b1d42e67fe243a99ff613.png

Java里面equals是Obect类里面定义的方法,今天我们就来研究一下equals的作用。equals的作用

Java里的equals是用来判断两个对象之间是否相等。

equals需要满足下列条件:

自反性:对于非空a,a.equals(a)总是为true
对称性:对于非空的a、b,如果a.equals(b)为true,则b.equals(a)也为true
传递性:对于非空的a、b、c,如果a.equals(b)为true,b.equals(c)为true,则a.equals(c)也为true
一致性:对于非空的a、b,只要a、b未发生改变,a.equals(b)总是返回true或者false
非空性:对于非空的a,a.equals(null)一定为false

我们来看下Obejct的equals实现:

public boolean equals(Object obj) {
    return (this == obj);
}

可以看到,默认的情况下equals就是比较两个的==操作。那么==操作是比较什么呢?

  • 对于基本类型(int,byte,boolean,long,short,double,float,char),==操作比较值相等
  • 对于对象类型,比较两个对象的内存地址。
  • 对于封装类型和基本类型间的比较,编译器会转换为基本类型后再比较

下面这个对于某些人来说可能是个世界难题,

@Test
public void testEqualsInt(){
    int a1=1;
    Integer a2=new Integer("1");
    Integer a3=new Integer("1");
    Integer a4=1;
    Integer a5=1;
    Integer a6=999;
    Integer a7=999;
    //比较基本类型和封装类型,会转换为基本类型后比较
Assert.assertTrue(a1==a2);
    //比较基本类型和封装类型,会转换为基本类型后比较
Assert.assertTrue(a1==a3);
    //比较基本类型和封装类型,会转换为基本类型后比较
Assert.assertTrue(a2==a1);
    //比较对象地址,new出来的显然是不同的
Assert.assertFalse(a2==a3);
    //比较对象地址,这个套路比较深,java里面会的-128~127里面的整数做缓存,返回相同的对象,超出范围的才new
Assert.assertTrue(a4==a5);
    //比较对象地址,这个套路比较深,java里面会的-128~127里面的整数做缓存,返回相同的对象,超出范围的才new
Assert.assertFalse(a6==a7);
}

所以我们可以很简单的得出:

@RunWith(JUnit4.class)
public class EqualsTests {
    @Test
    public void testEquals(){
        Student o1=new Student("111");
        Student o2=new Student("111");
        Assert.assertFalse(o1.equals(o2));
    }
    @AllArgsConstructor
    public static class Student{
        private String name;

    }
}

我们尝试着重新equals方法

@AllArgsConstructor
public static class Student{
    private String name;

    @Override
    public boolean equals(Object obj) {
        //满足非空性
        if(obj==null){
            return false;
        }
        //自反性
        if(this == obj){
            return true;
        }
        if(!obj.getClass().equals(this.getClass())){
            return false;
        }
        Student student=(Student)obj;
        //比较名称
        if(this.name==null){
            return student.name==null;
        }
        return this.name.equals(student.name);
    }
}


可以看到,我们做了很多额外的检查,来保证这两个相等性,我们的junit

@Test
public void testEquals(){
    Student o1=new Student(null);
    Student o2=new Student(null);
    Student o3=new Student("1111");
    Student o4=new Student("1111");
    Student o5=new Student("2222");
    Assert.assertTrue(o1.equals(o2));
    Assert.assertFalse(o1.equals(o3));
    Assert.assertFalse(o1.equals(null));
    Assert.assertTrue(o3.equals(o4));
    Assert.assertFalse(o4.equals(o5));
}


我们可以用EqualsBuilder来快速重写equals方法

public static class Student{
    private String name;

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Student){
            return new EqualsBuilder().append(this.name,((Student) obj).name).isEquals();
        }
        return false;
    }
}


更简单的,如果我们使用lombock,可以直接添加,

@AllArgsConstructor
@EqualsAndHashCode(of = "name")
public static class Student{
    private String name;

}


注意,这边会同时重写hashCode,在下面的集合测试里我们不会使用这种方式,会影响Hash类型的集合的结果。

在java里面很多类都重写了equals,比如String类的

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在集合里的作用

@Test
public void testEqualsInArray(){
    Student o1=new Student(null);
    Student o2=new Student(null);
    Student o3=new Student("1111");
    Student o4=new Student("1111");
    Student o5=new Student("2222");
    ArrayList<Student> list=new ArrayList();
    HashSet<Student> set=new HashSet();
    list.add(o1);
    set.add(o1);
    Assert.assertTrue(list.contains(o1));
    Assert.assertTrue(list.contains(o2));
    Assert.assertTrue(set.contains(o1));
    //没有重写hashCode导致HashSet无法正确判断元素
Assert.assertTrue(set.contains(o2));

}

可以看到,在使用HashSet的时候,尽管我们的equals是返回相同的对象,但是运行结果依旧是false。有关这部分的知识我们会留到HashCode的部分加以说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值