Java向上、向下转型的作用

一、向上转型

这个是我们平时用的最多的,比如我们要定义某一个方法的时候,经常使用一个抽象类(父类)或者接口作为参数把他们的子类传递过去,在传递的过程中,这个子类默认就是进行向上转型的。下面通过三个类来描述这个转型的变化。

// 父类
public class Father {

    public void method(){
        System.out.println("这是父类的方法");
    }

}
// 子类
public class Son extends Father {

    @Override
    public void method(){
        System.out.println("这是子类的方法");
    }
    // 注意这个儿子特有的方法
    public void sonMethod(){
        System.out.println("这是子类特有的方法");
    }

}
//  子类
public class Girl extends Father {

    public void method(){
        System.out.println("这是女儿的方法");
    }

}

当我们使用下面的代码调用对应的方法method(),这个时候默认是进行了向上转型的。

public class Main {

    public static void main(String[] args) {
        Father son = new Son();
        Father girl = new Girl();
        son.method();
        girl.method();
    }
}

//运行结果:
//    这是子类的方法
//	  这是子类的方法

我们可以简单的理解为,我们声明了一个引用son,但前面的Father让jvm认为这是一个指向Father类的引用,所以这个引用只是记录了Father里面有的方法,当我们调用这个method()方法时,引用真正指向的是一个Son对象,所以实际执行的是Son方法。但是因为这个引用记录的父类里面没有子类的方法,所以当我们想访问子类的方法时,就会报错。

基于上面的这个理解,我们可以在父类中声明一个他特有的方法:

public class Father {

    public void method(){
        System.out.println("这是父类的方法");
    }
    public void methodFather(){
        System.out.println("这是父类特有的方法");
    }

}

之后我们在对向上转型的引用调用父类的这个方法:

public class Main {

    public static void main(String[] args) {
        Father son = new Son();
        son.methodFather();
    }
}

//运行结果:
// 		这是父类特有的方法

如此,我们可以得出结论(多态的实质):当一个父类引用指向一个子类对象的时候,它会默认的进行向上转型,这个引用调用某个方法的时候,首先会检查这个引用(父类)有没有这个方法,没有的话直接报错;有的话看对应的子类对象有没有重写了这个方法,有则执行子类的方法,没有则执行父类的方法。

二、向下转型

针对向上转型带来的一个问题——向上转型的引用无法访问子类的特有方法,这个时候便用到了我们的向下转型。对上面的主函数的代码做下面对的改变,便可以访问到子类对象特有的方法:

public class Main {

    public static void main(String[] args) {
        Father son = new Son();
        ((Son) son).sonMethod();
    }
}

//运行结果:
	// 这是子类特有的方法

注意这里的“向下”指的是声明的引用类型(比如上面的son是Father)与强制向下转换的类型(上面是Son)一个父与子的关系。