夜话Java编译时类型与运行时类型

引言

习惯了看一些android的书,不知为何近期突然感觉对Java并不是很熟。事情的起因也很简单,平时上网搜资料的时候会一并查看博主的其他博文,然而最近去发现好多Java的知识点并不是很熟,例如GC原理、ClassLoder原理(这两问题打算好好看下《深入理解Java虚拟机——JVM高级特性》),抑或是一些常用集合的底层实现,毕竟也快2年了,总不能在别人问我ArrayList和LinkedList的区别的时候,我只回答说,前者比较适合访问、遍历,后者则比较适合在(中间)插入和删除吧==!所以后续会在Java这一块补一补。
本来上面提及的几个问题我这周都查阅了一些资料,也都有了初步的了解,就差总结,可需要整理的资料都在公司电脑上,无奈,就只好先来谈谈今天这个话题——Java编译时类型与运行时类型


正题

Java的引用变量有两个类型,一个是编译时类型,一个是运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,会出现所谓的多态。因为子类其实是一种特殊的父类,因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,由系统自动完成。

以下面的一段简单的代码来简要的说明:

//父类
public class Animal {
    public String name = "Animal";

    public void dinner() {
        System.out.println("Animal dinning");
    }
}
//子类
public class Cat extends Animal {
    public String name = "Cat";

    @Override public void dinner() {
        System.out.println("Cat dinning");
    }
}
//测试代码
public class Main {

    public static void main(String[] args) {
        Animal animal=new Cat();
        System.out.println(animal.name);//Animal
        animal.dinner();//Cat dinning
    }
}

在下面这句代码中,Animal是编译时类型,Cat是运行时类型。

 Animal animal=new Cat();

再来看一段话:

引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法(意思是说:编写代码时,只能调用父类中具有的方法,如果子类重写了该方法,运行时实际调用的是运行时类型的该方法。程序在编译时,会在编译类型中检查是否具有所调用的方法,如果编写代码时,使用引用变量调用子类中的特有方法,或者调用重载了父类中的方法,而父类中找不到该方法,则会报编译错误),因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。

要访问子类中特有的方法和属性,在编写代码时,则必须进行类型转换。

—— 以上摘自《疯狂Java讲义》

小伙伴们看明白了没?我的理解是“属性找编译,方法找运行”。在上面的测试代码中:

Animal animal=new Cat();
System.out.println(animal.name);//Animal
animal.dinner();//Cat dinning

第2行中打印的是属性,所以找编译时类型–Animal,所以输出的是Animal类中的name属性值;
第3行是调用方法,找运行时类–Cat,所以调用的是Cat类中的dinner()方法。
现在是不是明白了些呢?


其他

  • .class其实是在Java运行时就加载进去的,获取到的是编译时类型

  • getClass()是运行程序时动态加载的,获取到的是运行时类型

小伙伴们可以通过下面的代码验证:

System.out.println(Animal.class.getSimpleName());//Animal
System.out.println(Cat.class.getSimpleName());//Cat
System.out.println(animal.getClass().getSimpleName());//Cat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值