重写equals方法到底是干啥啊?

首先抛出一个问题:

public static void main(String[] args) {
        System.out.println("字符串直接==:"+("qq"=="qq"));
        System.out.println("字符串equals判别:"+"qq".equals("qq"));

        String s1=new String("qq");
        String s2=new String("qq");
        System.out.println("字符串直接==:"+(s1==s2));
        System.out.println("字符串equals判别:"+s1.equals(s2));
    }

输出结果:

字符串直接==:true
字符串equals判别:true
字符串直接==:false
字符串equals判别:true

问题简述:String类的基本数据类型用==和equals()都可以直接判断内容,而String类的对象用equals可以,==却失灵了。

原因:==默认只能判断两个东西,对于基本数据类型直接判断值,对于引用数据类型判断其地址编码。两个String对象的地址不同(两个“qq”在内存中各有一块位置),==自然失灵。

至于两个String类基本数据类型怎么判断相等,涉及常量池的问题,简单来说就是当某个字符串第一次出现,常量池中存储其内容和地址,再次声明同一个字符串时直接调用常量池中的这个。

这样看起来equals似乎很灵活,好像既是不是一个对象也可以直接判断内容。那么我们看看其他类型如何:

class User{                                  //定义一个User类
        String name;
        int age;

        public User(String name, int age) {

            this.name = name;
            this.age = age;
        }
    public static void main(String[] args) {  
        User u1=new User("qq",11);           //创建两个User对象
        User u2=new User("qq",11);
        System.out.println(u1.equals(u2));    //equals判别对象是否相等 
        }
}

输出结果:

false

原因:equals方法的源代码如下:

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

也就是说,对于一般的数据类型(我们不知道有没有Object的子类重写过equals方法,但自己写的类一定没有重写过),调用equals和用==没有区别。

那么String为什么特殊呢?我们看String类的源代码:

 public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        return (anObject instanceof String aString)
                && (!COMPACT_STRINGS || this.coder == aString.coder)
                && StringLatin1.equals(value, aString.value);

我们可以看到String对象的内容(值/value)在底层是一个byte类型的数组,而String源代码重写了equals方法,在==判别之后又进行了关于value的判别。也就是说对String的equals方法能够考察到具体值。

那我们再看一个:

        String s1=new String("qq");
        String s2=new String("qq");

        Object o1=s1;                //String对象向上转型到Object
        Object o2=s2;
        
        boolean eo=o1.equals(o2);
        System.out.println("o1.equals(o2) is "+eo);
        
        
        Object o11=new Object();     //创建Object对象,其内容是String
        o11=1;
        Object o22=new Object();
        o22=1;
        System.out.println("o11==o22 is "+(o11==o22));
        System.out.println("o11.equals(o22) is "+o11.equals(o22));

测试结果:

o1.equals(o2) is true
o11==o22 is true
o11.equals(o22) is true

问题简述:Object类调用equals方法为什么还能具体判断内容是否相等?

原因:只要子类重写了,那么无论是父类对象还是子类对象再次调用,都会优先调用子类对象。

这样看来equals方法有点鸡肋,程序员们对于这个关键字很执着,于是对于不同类要重写equals。

代码如下:

class User{
    String name;
    int age;
    
    
    public User(String name, int age) {
        
        this.name = name;
        this.age = age;
    }
    
    public boolean equals(Object ano) {
        if(this==ano) {
            return true;
        }
        if (!(ano instanceof User)) {                
            return false;
        }
        User anouser = (User) ano;
        //System.out.println("参数向下转型————"+anouser);
        return  name.equals(anouser.name)&&age==anouser.age;
    }

这个代码是针对User类重写了关于User的equals方法,基本思想是逐个判断属性是否相等。

具体而言:代码13行表示:如果==成立,表示两个对象地址编码相同,那么内容一定是相同的。

代码16行表示:如果作为方法参数的对象ano不是User类,那么一定和调用此方法的this对象不同。

代码19行目的是将ano向下转型为User,毕竟只要User类对象才能和User对象相等。(为什么ano只能按照Object类型接收呢?因为重写方法要求方法名,参数均不变,当我们将User类作为参数时它会自动向上转型到Object类这才需要向下再转型。当然如果不重写equals方法,而是针对某个对象单独写判别方式肯定可以)。

代码21行表示:对于name属性和age属性分别判断是否相等。

新人入门,格外大佬多多指教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值