前言
动物有共性的行为,例如吃。狗属于动物中的一类,对于“吃"这种行为,又有自己独特的见解,“吃狗粮”。当我们把“狗”上升到“动物”的概念,“狗”可以使用“动物”中的“吃”的行为,尽管在实践中,狗仍是进行“吃狗粮”的行为,在java中属于子类的向上转型;当我们把“动物”下沉到“狗”的概念,“动物”可以使用“狗”中的“吃狗粮”的行为,但前提是这个动物被认定为狗,毕竟不是所有动物都吃狗粮,在java中属于父类的向下转型。
一、上下类型转换是什么?
向上转型:通过 new 关键字创建子类对象,赋值给 父类的引用变量,实现子类的向上转型
Parents a = new Child(); /* Child类继承了Parents类 * new关键字,创建了Child类的对象 * 赋值给了Parents类的引用变量 a * 实现了 Child()对象的向上转型 */
向下转型:通过 new 关键字创建父类对象,强制转换,赋值给子类,实现父类的向下转型
Parents b = new Child(); /* new 关键字,创建了Child类的对象 * 赋值给了Parents中的引用变量 b * 相当于创建了Parents对象 * 并且点明了Parents类和Child类的关系,Parents对象实际上为Child类的一个实例 * 进行强制转换时不会报错 */ Child c = (Child)b; /* 将引用变量 b 强制转换成 Child类的引用变量 c * 实现了Parents对象的向下转型 */
注意:
1.父类与子类的上下类型转换,两个类之间,必须通过extends关键字,有继承关系
2.向下转型时,父类不能直接通过 new 实例化 赋值给子类的引用变量,必须进行子类 的强制转换。举个例子,向上转型,我们可以把“鸭脖”上升到“食物”这一层次;向下转型, 我们不能直接将“食物”下降到“鸭脖”这一层次,因为食物是广泛的,你怎么知道它是鸭脖, 不是老鼠头呢?所以向下转型时,我们还要多一句“这就是鸭脖”,鸭脖 c =(鸭脖)b;
3.向下转型时,Parents b = new Child(); 乍一看,这不是向上转型吗?是的,子类对象实例化,赋值给了父类,相当于创建了父类对象 b。向下转型时,少了这句话,就没有明确 b 实际上是子类的一个实例化对象,强制转换时,Child c =(Child)b; 会报错,不能强制转换
4.无论是创建父类子类对象,还是进行上下类型转换的代码,都要在方法中才能用
5.即使向上转型,转型为父类,调用父类方法,若被子类覆写过,仍然调用的是子类覆写过后的方法 ,因为本质上是子类实例化对象,赋值给了父类,归根到底还是子类对象
二、使用方法
1.父类与子类的转换
(1)创建父类 Food类,创建 nutrition()方法,num属性
package projectMy; public class Food { void nutrition(){ System.out.println("营养成分:糖类,蛋白质,脂肪,无机盐,维生素,水"); } int num = 1; }
(2)创建子类 DuckNeck类,覆写 nutrition()方法,创建 shape()方法
package projectMy; public class DuckNeck extends Food{ void nutrition() { System.out.println("营养成分:蛋白质,无机盐,脂肪,水"); } void shape() { System.out.println("形状:长条脖子"); } }
(3) 创建Demo类,进行类的上下类型转换
one.向上转型
package projectMy; public class Demo { public static void main(String[] args) { Food food1 = new DuckNeck(); //子类对象实例化,赋值给了父类,实现向上转型 food1.nutrition(); //调用父类方法,覆写过即为子类方法 System.out.println("food1.num"); //调用父类的属性 } }
输出结果:
问:输出结果是鸭脖的营养元素,不是父类中的营养元素,有没有发现,即使子类不进行向上转型,子类继承着父类。照样可以实现输出结果中的内容?
答:向上转型的意义在于多态性,模块化,这种方法允许我们编写更多可以处理的泛型代码,多种类型的对象,而不必为每个对象编写单独的代码。
two.向下转型
package projectMy; public class Demo { public static void main(String[] args) { Food food2 = new DuckNeck(); DuckNeck duckNeck = (DuckNeck) food2; duckNeck.shape(); duckNeck.nutrition(); System.out.println(food2.num); } }
输出结果:
该传串代码,创建父类对象 food2,强制向下转型为子类 duckNeck对象,可以调用子类独有的shape()方法,覆写的方法,父类原本的属性。
向下类型转换,可以用于生成初始化的对象,用户自定义选择,例如生成一个食物,用户可以根据自己的需要选择,将这个食物具体为面包,鸭脖等等,这时通过 向下类型转换 即可实现。
2.instanceof关键字
instanceof关键字:判断父类与子类之间的继承关系是否正确
语法: 子类对象名 instanceof 父类类名/接口名称
实操展示:
boolean result = child instanceof Parents; System.out.println(child instanceof Parents); /* child 为子类对象 Parents 为类名 * child 对象 是否为父类的继承对象 * 结果为布尔值,赋值到 result 对象 */
输出结果:true
注意:
1.instanceof关键字,只能在类与类是父类子类的继承关系时使用。类和类之间没有继承关系时, 用instanceof判断,会报错。
2.如果是子类的父类的父类,判断子类是否继承父类的父类,可以使用instanceof关键字,返回 ture 值。
假设 B类 继承 A类,C类 继承 B类
C c = new C(); system.out.println(c instanceof A);
输出结果: true
3. 可以理解为,instanceof关键字,判断父类和子类的关系是否颠倒,没有,返回true值;关系颠倒,返回false值。
总结
以上就是父类与子类的上下类型转换,和instanceof关键字。如果对文章中“接口”概念不太熟悉,可以看up主空间的下一篇文章。