012.继承的细节,向上转型 、向下转型
1.查看下面的代码有啥不一样的地方?试着运行一下查看一下结果吧。
package com.qx.test; public class A { int age = 20 ; void test() { System.out.println(age); } } class B extends A { int age = 22; void test() { System.out.println(age); } } class B extends A { int age = 22; void test() { super.test(); } }
2.向上转型:栈内存的票是父类的类型
(1)向上转型的代码:
package com.qx.jicheng; public class A { int age = 20; void test() { System.out.println(age); } }
package com.qx.jicheng; public class B extends A{ int age = 22; void test() { System.out.println(age); } }
package com.qx.jicheng; public class Entrance { public static void main(String[] args) { A a = new B(); a.test(); } }
(2)向上转型的特点
①对于成员方法
去父类寻找这个方法(再次强调是通过方法名称和参数列表)
a.若这个方法父类不存在,则不能通过编译。
b.若这个方法父类存在,则访问的是子类的方法。
package com.qx.jicheng; public class A { int age = 20; void test() { System.out.println("test++++A"); } }
package com.qx.jicheng; public class B extends A{ int age = 22; void test() { System.out.println("test++++B"); } void test1() { System.out.println("test1++++B"); } }
package com.qx.jicheng; public class Entrance { public static void main(String[] args) { A a = new B(); a.test1(); } }
②对于成员变量
a.父类不存在这个成员变量,则不能通过编译
b.仅仅能访问到父类的成员变量!
package com.qx.jicheng; public class A { int age = 20; void test() { System.out.println("test++++A"); } }
package com.qx.jicheng; public class B extends A{ int age = 22; void test() { System.out.println("test++++B"); } }
package com.qx.jicheng; public class Entrance { public static void main(String[] args) { B b = new B(); test(b); /** * B b =new B() * test(b) * 上述代码等价与 * C c = new C() * test(c) */ } static void test(A a) { /** * 1: a.可以找到的方法有a.test()、a.age * 2. 如果放进去的是b类型的会有 A a = b; * 3. a.test()如果调用test方法,一定调用的是b的test方法 * 4. 默认会有一个向上转型 * 5. 如果是A-->B-->C这种情况实际上, */ a.test(); } }
③方法参数列表中的向上转型(特点同上面两点)
(若存在方法的重载,并且重载后的方法参数列表都是父类,则选取结构图中最近的方法调用)
package com.qx.jicheng; public class A { int age = 20; void test() { System.out.println("test++++A"); } }
package com.qx.jicheng; public class B extends A{ int age = 22; void test() { System.out.println("test++++B"); } }
package com.qx.jicheng; public class C extends B{ }
package com.qx.jicheng; /** * A-->B-->C */ public class Entrance { public static void main(String[] args) { C c= new C(); test1(c);//这里最后会调用起 } static void test1(A a) { a.test(); } static void test1(B b) { //调用这里哦 } }
3.向下转型
当我们用子类的凭证去指向父类的凭证时,就叫做向下转型.
class A
class B extends A
class C extends A
那B类是子类,A类是父类.
对于B类,如果我们想使用B类. 则正常的实例化过程如下:
B b=new B();
那向下转型表示如下:
B b=new B();
A a=b;
B b=(B)a;
注意:向下转型可能会产生运行时的错误: A-->B-->C或者A-->B 、 A-->C
C c=new C();
A a=c;
B b=(B)a;
一般向下转型正确的话:
①一定经历了向上转型
②转型到的可以是对象的真实类型或者对象的父类(一个对象真正的类型是它自己本身的类)
向下转型的特点
①可能会产生运行时的错误(编译不会报错)
②向下转型并不一定会转到真正的类型上,如果仍然转到的是一个父类。则遵从我们上面所说的向上转型的特点.
③如果没有报错,对于转型后的访问和正常申明后(可能也涉及到向上转型)的访问没有区别
避免向下转型报错的办法
使用instanceof 关键字
①关键字介绍:判断 对象 是不是 该类的子类或者本身。
举例: a instance of A 即a是否是A类本身或者是A类的子类.
②具体使用:利用instanceof 判断后,进行向下转型从而使用子类特有的方法.