理解Java的类型信息

本文深入探讨Java中的运行时类型信息(RTTI)概念及其应用场景,如多态与反射机制,并介绍了Class对象的作用及如何获取Class对象。

Java的类型信息

  • 理解RTTI(运行时类型信息)

    RTTI原本是C++里面的名词,在Java的官方文档中好像没有出现过这个名词,其在java界为人熟知主要还是因为B大 的《Thinking In Java》吧,毕竟在java界如同圣经般的存在。

    那么其具体是什么意思呢?其主要应用还是java的多多态与反射机制。举个栗子:

    public  class Animal extends Object{
    public void eat(){
        System.out.println("什么都吃");
    }
    }
    
    public class Dog extends Animal {
    @Override
    public void eat() {
        // TODO Auto-generated method stub
        System.out.println("吃骨头");
    }
    }
    
    public static void main(String[] args) throws ClassNotFoundException {
        Animal a=new Dog();
            a.eat();
    }
    
    //这里通过一个Animal的引用指向Dog对象,调用a的eat的时候实际调用的是dog的方法,底层实现就是通过RTTI找到的真实的对象

    当有一个指向基础型别(父类)的reference(引用)时,RTTI机制让你找出其所指的确切型别,由于Dog是在运行期才创建的,RTTI就是帮助我们在运行期正确判断对象类型。从而运行正确的方法。

  • RTTI的使用形式

    1. 传统的类型转换,通过RTTI保证类型转化的正确性。如果转化错误,会抛出异常。
    2. 通过Class对象查询运行时所需信息时。
    3. 使用instancef查看某个对象是否是某个类的实例的时候。
  • Class对象

    Class算是Java中一个非常特别的类了,普通的类可以描述为对象的实例的集合,那么Class类可以描述为普通的类的描述信息实例的集合。

    每一个类类都有一个Class对象,其被保存在编译后产生的.class文件中,通过JVM的类加载器生成这个对象。所有类都是在第一次使用时,才动态加载到JVM中的(当程序创建第一个对类的静态引用就会加载这个类,其实构造方法也是静态方法,虽然其前面并没有static关键字。)

    当需要使用某个类时,编译器先会判断该类是否已经加载,如果没有,先会根据类名查找.class文件,加载到内存中。

    Class<?> clazz = Class.forName("com.forever.rtti.Dog");

    通过Class的静态方法可以获得clazz对象,这里的clazz保存了Dog类的信息,包括其实现的接口以及父类的类信息,其成员属性与方法的信息。并且在获取对象信息的时候,类加载器会将该类加载到内存中。

    除了使用上面的方法外,我们还可以使用其他的方法获取Class对象

    //方法2(使用该方法时,JVM是不会加载Dog类到内存的)
    Class<?> clazz = Dog.class;
    //方法3
    Dog dog=new Dog();
    Class<?> clazz = dog.getClass();
  • 加载类的过程

    1. 加载:通过类加载器,通过查找字节码文件(.class获取网络获取),从字节码文件中创建Class对象。

    2. 链接:验证类中的字节码,为静态域分配空间,必要时会解析创建这个类所需要的对其他类的引用。

    3. 初始化:执行静态初始化器和静态初始化块。

      public class Dog extends Animal {
      public static final int i=0;
      
      public static int j=2;
      
      static {
          System.out.println("dog init");
      }
      }
      
      public static void main(String[] args) throws ClassNotFoundException {
          System.out.println(Dog.i);
          System.out.println(Dog.j);
      }
      //打印结果
      0
      dog init
      2

      说明在对 public static final int i=0(编译期常量)访问时是不会初始化类的。

      对非编译期常量访问时会初始化类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值