java基础|向上、向下转型

向上、向下转型 基础知识多肽回顾:
1.多肽是方法的多肽,不是属性的多肽(多肽与属性无关)。
2.多肽的存在有三个必要条件:继承、方法重写、父类引用指向子类对象。
3.父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多肽就出现了。
一、向上转型 原文链接

class Animal { public void eat(){ System.out.println("父类的 吃..."); } } class Bird extends Animal{ @Override public void eat(){ System.out.println("子类重写的父类的吃吃吃..."); } public void fly(){ System.out.println("子类新方法飞飞飞..."); } } public class Sys{ public static void main(String[] args) { Animal b=new Bird(); //向上转型 b.eat(); //b.fly(); b虽指向子类对象,但此时子类作为向上的代价丢失和父类不同的fly()方法 sleep(new Male()); sleep(new Female()); //传入的参数是子类-----!! } public static void sleep(Human h) {//方法的参数是父类------!!! h.sleep(); } }

public class Human { public void sleep() { System.out.println("父类人类sleep.."); } } class Male extends Human{ @Override public void sleep() { System.out.println("男人 sleep.."); } } class Female extends Human { @Override public void sleep(){ System.out.println("女人 sleep.."); } }

输出:
子类重写的父类的 吃吃吃…
男人 sleep…
女人 sleep…
详解:
  1. 向上转型的实现
    Animal b=new Bird(); //向上转型 b.eat(); // 调用的是子类的eat()方法 b.fly(); // 报错!!!!!-------b虽指向子类对象,但此 时子类作为向上转型的代价丢失和父类不同的fly()方法------

2.为何不直接Bird b=new Bird(); b.eat() 呢?
这样就没有体现出面向对象的抽象的编程思想呀,降低了代码的可扩展性.
3.向上转型的好处?
sleep(new Male()); //调用方法时传入的参数是子类 sleep(new Female()); public static void sleep(Human h) //方法的参数是父类{h.sleep(); }

如上代码就是用的向上转型,若是不用向上转型,那么有多少个子类就得在这儿写多少种不同的睡觉方法~~~~~~
说到这里是不是还是感觉云里雾里,再上个例子:
Person 可以表示为一个抽象的东西就是人。比如说人可以唱歌, 就好比Person类中有一个sing方法.
那么这个抽象的类(Person 人)可以具体到两类或者更多类 比如 男人,女人 。
Man extends Person 或者 Woman extends Person
那么男人 还有 女人 分别实现sing方法。 因为男人和女人唱歌总还是有区别的嘛。
当 Person p = new Man(); p.sing(); 这个时候就是调用男人唱歌的sing方法
当 Person p = new Woman(); p.sing(); 这个时候就是调用女人的唱歌的sing方法
这样其实就是一个java的继承,多态. 利于程序扩展. 你需要理解这种设计方式,会让你写出更易维护,简洁的代码。
二、向下转型
class Fruit{ public void myName(){ System.out.println("我是父类水果..."); } } class Apple extends Fruit{ @Override public void myName() { System.out.println("我是子类苹果..."); } public void myMore(){ System.out.println("我是你的小呀小苹果~~~~~~"); } } public class Sys{ public static void main(String[] args) { Fruit a=new Apple(); //向上转型 a.myName(); Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的) aa.myName(); //向下转型时调用的是子类的 aa.myMore(); ; Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错 aaa.myName(); aaa.myMore(); } }

输出:
我是子类 苹果…
我是子类 苹果…
我是你的小呀小苹果~~~~~~
Exception in thread “main” java.lang.ClassCastException: com.sheepmu.Fruit cannot be cast to com.sheepmu.Apple
at com.sheepmu.Sys.main(Sys.java:30)
【java基础|向上、向下转型】由此得到向下转型的意义:父类引用可以使用子类的新增方法
详解:
1.正确的向下转型
Fruit a=new Apple(); //向上转型 a.myName(); Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的) aa.myName(); aa.myMore();

a指向子类的对象,所以子类的实例aa也可以指向a啊~~
向下转型后因为都是指向子类对象,所以调用的当然全是子类的方法~~
2.不安全的向下转型
Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错 aaa.myName(); aaa.myMore();

f是父类对象,子类的实例aaa肯定不能指向父类f啊~~~
3.Java为了解决不安全的向下转型问题,引入泛型的概念
4.为了安全的类型转换,最好先用 if(A instanceof B) 判断一下下
这里引出一个问题:JAVA的面向对象应该怎样理解。(之前就突然被一个面试问到对面向对象、面向过程的理解)有很多种答案,这里是B站上看到的一个老师讲的。
所有的程序其实只有三个核心元件:变量、选择语句、循环语句。
面向过程变成:我们可以通过方法,来把这三个东西放在一起。然后通过方法一方法二串联起来,最终形成一个程序。
面向对象:对象,它是一个更高级的组织方式。我们可以把方法、变量放到对象里面。更高级的组织形式可以做更复杂的程序。

    推荐阅读