编译时类型和运行时类型---关于类型转换的原理解析

来源:互联网 发布:网络文明有哪些 编辑:程序博客网 时间:2024/06/08 16:04

转:https://www.cnblogs.com/aademeng/articles/6190143.html

先上代码: 
Class A:

package testone;public class A {    String a = "This is Class A!";    public String getString()    {        return this.a;    }}

Class B:继承Class A

package testone;public class B extends A{    String a = "This is Class B!";      public String getString()    {        return this.a;    }}

测试代码:

package testone;public class mainTest {    public static void main(String[] args)     {        A a1 = new A();        System.out.println(a1.getClass()+"  "+ a1.getString()+"  "+a1.a);        B b1 = new B();        System.out.println(b1.getClass()+"  "+ b1.getString()+"  "+b1.a);        a1 = b1;         System.out.println(a1.getClass()+"  "+ a1.getString()+"  "+a1.a);        b1 = (B)a1;        System.out.println(b1.getClass()+"  "+ b1.getString()+"  "+b1.a);        A a2 = new B();       System.out.println(a2.getClass()+"  "+ a2.getString()+"  "+a2.a);    }}

测试结果一:

class testone.A  This is Class A!  This is Class A!class testone.B  This is Class B!  This is Class B!class testone.B  This is Class B!  This is Class A!class testone.B  This is Class B!  This is Class B!class testone.B  This is Class B!  This is Class A!

   
  从这个结果可以看出类继承时,子类会覆盖与父类相同的属性。总结一点就是:对象访问变量看声明,访问方法看实际对象类型(new出来的类型)。这在以前的博文(Java中对象的属性不体现多态性)也提到了。也可以说:属性无多态,而方法具有多态。 
   
  什么是多态?所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。 
   
  而我对通过getClass()方法返回的对象的类类型感到疑惑。注意最后三条赋值语句,为什么赋值之后,输出结果都显示它们是Class B的对象?既然都是Class B的对象,为什么只有此时只有对象b1可以访问Class B的方法? 
  原来getClass()返回的是Object的运行时类。 
  Java中的许多对象(一般都是具有父子类关系的父类对象)在运行时都会出现两种类型:编译时类型和运行时类型,例如:Person person = new Student();这行代码将会生成一个person变量,该变量的编译时类型是Person,运行时类型是Student。 
  “说明一下编译时类型和运行时类型:Java的引用变量有两个类型,一个是编译时类型,一个是运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,会出现所谓的多态。因为子类其实是一种特殊的父类,因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,由系统自动完成。引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法(方法表)。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性“。 
  ”引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性“。 
  在看一下Java API中关于getClass()方法的讲解: 
  这里写图片描述