想分享一下我对向上转型和向下转型的认识:

一、三种向上转型

向上转型,就是将子类对象赋值给父类类型的引用变量的操作,我们有三种方式可以做到向上转型

注意:向上转型后这个引用无法再调用子类自己的方法了,但重写的方法可以,而且还会调用到子类的方法

1.假设此时有父类Animal,继承父类的子类Dog:

public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Dog();

        Animal animal2 = new Animal();
        animal2 = new Dog();
    }
}

无论是一行解决还是拆成两行来写都是同样的效果,通过这一操作,我们成功将子类对象Dog赋值给了父类类型的引用animal1和animal2。

2.通过传递引用,要求传过去的引用类型为父类Animal

public static void func1(Animal animal) {
    System.out.println("AA");
}
public static void main(String[] args) {
     Dog dog = new Dog("旺财",1);
     func1(dog);
}

此时dog传过去之后完成了一次隐式的向上转型,注意,此时这个dog比较特殊,dog这个引用依然能调用子类的方法,父类的方法同样可以调用,正常的引用向上转型之后,不能再调用子类自己的方法,这也是向上转型的缺点。

3.有返回值类型的父类类型方法

public static Animal func2() {
    Dog dog = new Dog("旺财", 2);
    return dog;
}

返回值的类型被声明为Animal(父类),实际返回的是Dog类型的对象(子类),返回式,Dog对象同样会被隐式转换为父类类型Animal的引用。

二、向下转型(有风险)

向下转型跟类型的强制转换很像,所以风险自然会有

public static void main(String[] args) {
     Animal animal = new Dog("旺财",2);
     Bird bird = (Bird)animal;
}

此时我们成功将animal这个引用转换为Bird类型了

1.风险问题

假设Bird有一特殊方法fly

public class Bird extends Animal {
    public Bird(String name, int age) {
        super(name, age);
    }

    public void fly(){
        System.out.println(this.name+"飞起来了");
    }
}

之后我们用向下转型为Bird型的引用animal来调用Bird类型中的方法fly

public static void main(String[] args) {
     Animal animal = new Dog("旺财",2);
     Bird bird = (Bird)animal;
     bird.fly();
}

猜猜这个旺财会不会飞起来?运行一下,发现系统报错,旺财这条狗没长翅膀当然不会飞啦,这也是向下转型的风险所在

三、instanceof

  Java中的一个类型判断运算符,核心作用是判断一个对象的运行时类型是否是某个类的实例

实例:

public static void main(String[] args) {
    Animal animal = new Dog("旺财", 2);
    if(animal instanceof Dog){

        System.out.println("当前引用类型是Dog类型");
    }
    else{
        System.out.println("当前引用类型不是Dog类型");
    }
}

instanceof用于判断当前引用类型是否为某个类型,当然结果必然是Dog类型啦

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐