Java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时的类型由声明该变量时实用的类型决定,运行时的类型由实际赋给该变量的对象决定
转载请注明: http://blog.csdn.net/qduningning/article/details/8075624
如果编译时类型和运行时类型不一致,就会出现所谓的多态。
因为子类其实是一种特殊的父类,因此Java允许吧一个子类对象直接赋给一个弗雷德引用变量,无需做任何类型转换,或者成为向上转型(upCasting UML图中父类在上),向上转型由系统自动完成,向下转需要显式也就是强制转换。
但把一个之类对象直接赋给父类引用变量,父类 父=new 子类,父类引用变量的编译时类型是父类,而运行时类型是子类。
当运行时调用该变量的方法时,其行为总是想之类方法的行为,而不是父类的方法行为,这将出现相同类型的变量,执行同一个人方法时呈现出不同的行为特征,这就是多态。
引用变量再编译阶段只能调用其编译时类型所具有的方法,但在运行时着则运行它运行时类型所具有的方法(可以通过反射机制来运行时类型所具有的特殊方法)。特别的,对象的属性不具有多态性 。
而向下转型时如Person p = new Student();这行代码将会产生一个p变量,该变量的编译类型为Person,运行时类型是Student,除此之外,还有更极端的情况,程序运行时节收到外部传入的一个对象,该对象的便宜类型是Object,但程序有需要调用该对象运行类型的方法。
为了解决这些问题,程序需要在运行时发现对象和类的真是信息,为了解决这个问题,我们有两种做法:
- 地重视假设再便宜和运行时都完全知道类型生物具体信息,在这种情况下,我们可以直接显示用instanceof运算符进行判断,再利用强制类型转换将其转换成其运行是类型生物变量即可。
- 第二种是编译时根本无法获知该对象和类可能输入哪些类,程序职能依靠运行时信息来发现该对象和列的真实信息,这就必须使用反射。
使用反射有两个好处:
- 代码更安全,、程序在编译阶段就可以检查需要访问的Class对象是否存在
- 程序性能更高,因为这种方式无需调用方法,所以性能更好。
测试程序:
public class Duotai {
public int num = 10;
public void foo(){
System.out.println("Duotai");
}
public static void main(String[] args) {
Duotai duotai = new SubClass();
Duotai duotai2 = new SubClass2();
duotai.foo(); //对象的方法具备多态性
duotai2.foo();
System.out.println(duotai.num); //对象的属性不具备多态性
System.out.println(duotai2.num);
try {
Class<?> clazz = Class.forName("com.znn.cehi.SubClass");//本包
Method method = clazz.getMethod("teShu");
method.invoke(clazz.newInstance());
Method methodPara = clazz.getMethod("teShuPara",int.class,String.class);
methodPara.invoke(clazz.newInstance(),111,"sss");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class SubClass extends Duotai{
public int num = 10;
@Override
public void foo() {
System.out.println("SubClass");
}
public void teShu(){
System.out.println("子类特有方法");
}
public void teShuPara(int num,String s){
System.out.println("子类特有有参方法"+num+" "+s);
}
}
class SubClass2 extends Duotai{
public int num = 20;
@Override
public void foo() {
System.out.println("SubClass2");
}
public void teShu(){
System.out.println("子类2特有方法");
}
public void teShuPara(int num,String s){
System.out.println("子类2特有有参方法"+num+" "+s);
}
}
运行结果:
SubClass
SubClass2
10
10
子类特有方法
子类特有有参方法111 sss
SubClass2
10
10
子类特有方法
子类特有有参方法111 sss
转载请注明: http://blog.csdn.net/qduningning/article/details/8075624