instanceof为什么判读之后 还要进行强制类型转换

376 阅读3分钟

本文使用Java8的版本。

我们直接看代码:

public class Phone {
    public String name;
    public int price;

    public Phone(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    //equaLs方法进行重写:
    public boolean equals(Object obj) {
        System.out.println(obj); //Phone@1b6d3586
        if (obj instanceof Phone) {//是否属于Phone类的对象
            if (this.getName().equals(obj.getName()) && this.getPrice() == obj.getPrice()) {
                return true;
            }
        }
        return false;
    }
} 

写个测试类:

public class Demo {
    public static void main(String[] args) {
        Phone p1 = new Phone("P30",5000);
        Phone p2 = new Phone("P30",5000);
        System.out.println(p1.equals(p2)); //true
    }
} 

我定义了一个Phone类,并且重写equals方法,判断两个类,如果name和price都一样,就认为两个对象一样。

我们来运行一下代码,先编译

发现编译出错,说是找不到getName()和getPrice()两个方法。而且还提示说obj是Object,为什么obj不是Phone呢?

我们先把代码改为正确的写法,只需要修改equals就行:

public boolean equals(Object obj) {
        System.out.println(obj); //Phone@1b6d3586
        if (obj instanceof Phone) {//是否属于Phone类的对象
            Phone other = (Phone) obj;//将obj转为Phone类型:
            if (this.getName().equals(other.getName()) && this.getPrice() == other.getPrice()) {
                return true;
            }
        }
        return false;
    }

多了一句Phone other = (Phone) obj;这句强制类型转换,然后下面是通过other.getName()other.getPrice()调用的,而且打印obj对象,发现他就是Phone实列,通过 if (obj instanceof Phone)判断是true,说明obj就是Phone,那为什么还需要类型强转呢?既然obj是Phone,那为什么就不能直接obj.getName()这种调用呢?

这边涉及到多态的知识

多态

多态: 是指同一行为,具有多个不同表现形式。

前提【重点】

  1. 有继承或者实现关系

  2. 方法的重写【意义体现:不重写,无意义】

  3. 父类引用指向子类对象【格式体现】

    父类类型:指子类对象继承的父类类型,或者实现的父接口类型。

 多态的运行特点

调用成员变量时:编译看左边,运行看左边

调用成员方法时:编译看左边,运行看右边

    Animal a = new Panda();
    //编译看左边的父类中有没有age这个属性,没有就报错
    // 在实际运行的时候,把父类age属性的值打印出来
    System.out.println(a.age);
    //编译看左边的父类中有没有testPanda这个方法,没有就报错
    //在实际运行的时候,运行的是子类中的testPanda方法
    a.testPanda();

回头看我们equals方法的参数是Object,他是所有类的基类,所以可以接受所有类。所以形参可以理解为:Object obj = p2 = new Phone("P30",5000); 再简化一下就是Object obj =  new Phone("P30",5000);

那么编译看左边,obj在编译阶段就是Object了,那么obj本身肯定没有getName方法的直接obj.getName()自然就找不到方法了。所以刚开始报错就在编译阶段报的,但是instanceof是在运行阶段。

参考文章:Java多态

instanceof的用法 为什么判读之后 还要进行强制类型转换

stackoverflow.com/questions/4…