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 判断后,进行向下转型从而使用子类特有的方法.