要转型,首先必须要有继承。继承是面向对象语言中一个代码复用的机制,简单的来说就是子类继承了父类中的非私有属性和方法,然后子类可以继续扩展自己的属性和方法。

向上转型:子类对象转为父类,简单的理解就是一个父类类型的子类对象,类似于这样:Father f = new Son();(Father可以是父类或者接口,Son是子类)

向下转型:父类对象转为子类,简单的理解就是将父类类型的对象转为子类类型,类似于这样:Son s = (Son)f;

但是在这里要注意:向上转型是安全的,但是向下转型却不是安全的,例如:父类本身引用的对象就是父类本身,而非向上转型的子类对象,那么此时的向下转型就是不安全的,运行时会报java.lang.ClassCastException错误。他可以使用instanceof来避免出此类错误即能否向下转型。(所以由这里我们也可以知道只有向上转型之后才可以向下转型)

也许我们刚开始的时候都有一个这样的问题:直接Son s = new Son();不是更方便吗?下边是一个例子看看就知道为什么用它了:

public class Human {
    public void sleep() {
        System.out.println("Human sleep..");
    }
    public static  void doSleep(Human h){
           h.sleep();
          
    }//此时传递的参数是父类对象,但是实际调用时传递子类对象,就是向上转型。

    public static void main(String[] args) {
        Human h = new Male();// 向上转型
        doSleep(new Male());//此处匿名子类对象,当然实际应用时应该是用上面的向上转型公式(直接:doSleep(h);,然后下边
                      //也就需要用Human h1 = new Female();然后再doSleep(h1);这里使用的是匿名类对象),然后将子类对象
                    //传递进来,这样以后好在向下转型,此处没有向下转型,所以直接用了匿名类对象。
        doSleep(new Female());
        
    }
}

class Male extends Human {
    @Override
    public void sleep() {
        System.out.println("Male sleep..");
    }
}

class Female extends Human {
    @Override
    public void sleep() {
        System.out.println("Female sleep..");
    }

}

还有一点要注意:在使用向上转型时,父类引用会丢失子类的方法(不包括重写过的,这个下边说),也就是说在引用子类的方法时会找不到方法;然后就是一个新的东西:“动态绑定”,这个是父类引用在调用父类方法时如果子类重写了父类的这个方法,那么就会根据这个引用指向子类重写的这个方法,而不是父类原来的方法(这个方法就是覆盖Override)。这个调用过程被称为动态绑定。