菜鸟学JAVA之——Object的toString、equals和hashCode方法,instanceof关键字

instanceof

格式

对象 instanceof 类型:判断这个对象是不是这个类型的对象,如果是,输出true

 System.out.println(A instanceof B);

其中A为一个对象,B表示一个类或者一个接口,当 A为B的对象,或者是其直接或间接子类,或者是其接口的实现类,则输出true,否则输出false。 (使用instanceof关键字做判断时, instanceof 操作符的左右操作数必须有继承或实现关系

  • 如果A是基础数据类型则直接编译不通过(instanceof 运算符只能用作对象的判断)

  • 如果A为null,则直接返回false(java的一种规范)

  • 在判断某个类或接口的对象是不是其他类(或接口)的实例,一定要首先进行向上转型,然后才可用instanceof关键字进行判断,这是基本操作规范。

一般在写类型强转时,不确定当前拿到的对象类型是什么,只是有一个猜测,所以在这里就判断一下,把猜测的类型输入到后面,如果true就可以转

if(usb1 instanceof USBImpl) {
     (USBImpl)usb1
}

Object

  • Object是所有类的父类,所有类都默认继承他
  • Object有一个空的无参的构造方法,所以任何类都默认有一个无参的构造方法
  • 任何一个类都是Object的子类,任何一个对象都是Object的对象

下面主要来看一下Object的源码里的一些方法

1.toString()方法
public class ObservObject {
    @Override //注解,有意义,只有在父类里有这个方法才不抛错
    public String toString() {  //Object的toString方法
        //return super.toString();//这里的super代表的就是Object的,而Object里的这个方法什么都没干
        return "我是ObservObject";
    }
}

场景类

public class Main {
    public static void main(String[] args) {
        ObservObject observObject = new ObservObject();
       // System.out.println(observObject);//括号里的observObject默认调用toString方法,即observObject.toString()。在ObservObject类重写toString方法之前,则调用的是Object的toString方法,会输出一串“数字”
        System.out.println(observObject);//重写后输出:我是ObservObject
    }
}

给一个场景,要计算的a+b算出来结果是错的,我不知道到底是传的参数是错的还是方法是错的,就可以用toString输出检查一下。

class ObservObject {
    private int age = 3;
    private int height = 4;
    public int sum() {
        return 8;
    }
    @Override
    public String toString() {  
        return "我是ObservObject:"+"age是:"+age+","+"weight是:"+weight;
    }
}
public class Main {
    public static void main(String[] args) {
         ObservObject observObject = new ObservObject();
         System.out.println(observObject);//输出:我是ObservObject:age是:3,weight是:4   你可以根据这个判断
    }
}
//上面的toString格式其实可以不用自己写,可以用工具自动生成(右键点击Generate),这样可以方便调试代码
2.equals()方法

父类有equals方法,但默认比较的是地址。但是为啥我们前面学的equals比较的是内容呢,这是因为所有类都默认继承Object类,当时我们调用的equals方法是String类重写的equals方法,String类的源码里写的是比较的内容

下面我们新建一个类,重写一下父类的equals方法,来实现他的内容比较

public class ObservObject {
        private int a;
        private int b;
    
        public ObservObject(int a, int b) {
            this.a = a;
            this.b = b;
        }
    
        @Override
        public boolean equals(Object obj) {
           // return true;如果直接这样写,那么只要调用ObserveObject的equals方法都会返回ture;
             if(this == o) { 
                return true;//如果地址相等,则内容一定相等
            }
            
            if(o instanceof ObservObject) { //判断一下,如果o不是ObservObject类型的那就不用做强转了,直接返回flase
                ObservObject that = (ObservObject)o;
                if(this.hashCode() != that.hashCode()) {//这块下面会解释
                    return false;
                }
                if(this.a != that.a) {  //判断内容
                    return false;
                }
                if(this.b != that.b) {
                    return false;
                }
                return true;
            } else {
                return false;
            }
        }
    }
public class Main {
    public static void main(String[] args) {
        ObservObject oo = new ObservObject(3,4);
        ObservObject observObject = new ObservObject(3,4);
        System.out.println(oo.equals(observObject));//输出true,如果在ObservObject中没有重写equals方法则返回的是false
    }
}

自己写类时最好把equals重写上,除非你不做任何比较,以上还不仅仅是equals方法

3.hashCode()方法

先了解一下哈希

哈希算法:任何一个实现不可逆过程的算法都叫做哈希算法

  • hash是一个函数,该函数中的实现就是一种算法,就是通过一系列的算法来得到一个hash值。
  • hash函数算出的值:1.不可复原。2.按原来的值再传一次得到的结果不会变
  • hashcode就是通过hash函数得来的,通俗的说,就是通过某一种算法得到的,hashcode就是在hash表中有对应的位置。
  • hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的对象存放在内存中的地址
  • 对象如何得到hashcode呢? 通过对象的物理地址转换成一个整数,然后该整数通过hash函数的算法就得到了hashcode。这个hashcode的值就是在hash表中对应的位置坐标。

下面重写一下Object类的hashcode方法

public class ObservObject {
        private int a;
        private int b;

        public ObservObject(int a, int b) {
            this.a = a;
            this.b = b;
        }

    @Override
    public int hashCode() {
            //注意,java底层的hashcode不是这样计算的,这里只是实现了一个简单的hashcode算法(与String里面的类似)
        int code = 0;
        code = code + this.b*31+31;
        code = code + this.a*31+31;
        return code;
    }
}
public class Main {
    public static void main(String[] args) {
        ObservObject oo = new ObservObject(3,4);
        System.out.println(oo);//输出:com.yau.foo.ObservObject@117   这个@后面的数就是hashcode(十六进制表示的)
    }
}

hashcode值代表这个对象特征值的编码,通过117不能推出a=3,b=4(不可逆)hashcode可以重复,比如a=4,b=3,算出来的hashcode一样。;

看一下String类中重写的hashcode方法

/*源码*/
public int hashCode() {
        int h = hash;  //h默认是0
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];   //这个一直加,溢出来可以循环,字符串有多长都可以算出hashcode值,现在就有可能出现重复,因为int值是有限的,而字符串是无限的,用有限的来表示无限的,一定会发生重复。
            }
            hash = h;
        }
        return h;
    }

equals方法和hashcode的关系

hashcode 在底层是做相同判断用的。Java里面规定,如果两个对象.equals为true,则他们的hashcode一定要相等(如果hashcode不相等则对象也一定不相等)。但如果两个对象的hashcode相等,不一定要equals返回true,因为很有可能两个对象得hashcode确实相等,而他们的对象确实不相等。总结一句话:equals为true则hashcode一定相等;hashcode相等,equals不一定为true;hashcode不相等则equals一定为false

所以在这里再补充一下上面得.equals方法。代码在上方

为什么equals方法重写的话,建议也一起重写hashcode方法?

比如:有个A类重写了equals方法,但是没有重写hashCode方法,看输出结果,对象a1和对象a2使用equals方法相等,按照上面的hashcode的用法,那么他们两个的hashcode肯定相等,但是这里由于没重写hashcode方法,他们两个hashcode并不一样,所以,我们在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。

hashcode的学习部分参考:https://blog.csdn.net/weixin_38405253/article/details/91922340

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值