Class类详解

Object类中的getClass()方法即返回一个Class类型的实例,那么 「Class类到底是什么?从何而来?又有什么作用呢?」

参考答案

Class类是什么?
先来简单了解一下Java虚拟机中类的加载过程:
「加载」阶段是「类加载」过程的第一个阶段,虚拟机需要完成以下三件事情:
  1. 通过一个类的全限定名来获取定义此类的二进制字节流(.class文件即保存着类的二进制数据)。
  2. 将该字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在Java堆中生成一个代表该类的java.lang.Class对象,作为方法区中该数据结构的访问入口。
也就是说,Class是一个保存着运行时类所有信息的类,即在程序运行时跟踪类且掌握着类的全部信息,故其也被称为反射的源头(有点儿小抽象)。
如何获取Class类对象?
共有四种方式来获取Class类的实例,如下:
@Test
// 需要提供异常处理
public void test() throws ClassNotFoundException{
    //1.通过运行时类的.class属性获取
    Class<Person> clazz1 = Person.class;
    System.out.println(clazz1);

    //2.通过运行时类的对象获取
    Person p = new Person();
    Class clazz2 = p.getClass();
    System.out.println(clazz2.getName());

    //3.通过Class类的静态方法获取
    String className = “com.whutqbchen.java.Person”;
    Class clazz3 = Class.forName(className);
    System.out.println(clazz3);

    //4.通过类的加载器获取
    ClassLoader cl = this.getClass().getClassLoader();
    Class clazz4 = cl.loadClass(className);
    System.out.println(clazz4.getName());
}
提示:在启动时,包含main方法的类被加载。它会加载所有需要的类。这些被加栽的类又要加载它们需要的类,以此类推。对于一个大型的应用程序来说,这将会消耗很多时间,用户会因此感到不耐烦。可以使用下面这个技巧给用户一种启动速度比较快的幻觉。不过,要确保包含main方法的类没有显式地引用其他的类。首先,显示一个启动画面;然后,通过调用Class.forName手工地加载其他的类。
Class类的实例可以做什么?
获取到运行时类的Class实例后,通过Class类的实例可以:
  • 通过newInstance()方法创建对应运行类的对象。
  • 获取其对应类的完整结构,如构造器、属性、方法、内部类、父类、所在的包、异常和注解等。
  • 调用对应的运行时类的指定结构,如属性、方法和构造器。
  • 反射的应用,即动态代理(又挖一坑)。
所以说,Class类是反射的源头,有一种「Class在手天下我有」的既视感。
这也是Java中「反射」技术的主要内容。
注意事项:
请注意,一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如,int不是类,但int.class是一个Class类型的对象。
另外,调用Class类实例的newInstance()方法动态创建类对象时,需要对应的运行时类中有空参的构造器,这个细节本人在面试Synopsys的时候被问到过。

源码阅读

通过Class类的实例获取运行时类的所有描述信息的代码较长,在此仅给出对应的方法描述,如下:
通过反射可访问的主要描述信息


    本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
    极客文库 » Class类详解

    Leave a Reply

    欢迎加入「极客文库」,成为原创作者从这里开始!

    立即加入 了解更多