Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
Class对象的生成方式如下:
1.Class.forName("类名字符串")
2.类名.class
3.实例对象.getClass()
通过一段小程序,来观察一下Class对象的生成的原理。
1.
2.
3.
4.
5. public class TestClass {
6.
7.
8.
9. public static void main(String[] args)
10.
11. {
12.
13. try {
14.
15. //测试Class.forName()
16.
17. Class testTypeForName=Class.forName("TestClassType");
18.
19. System.out.println("testForName---"+testTypeForName);
20.
21. //测试类名.class
22.
23. Class testTypeClass=TestClassType.class;
24.
25. System.out.println("testTypeClass---"+testTypeClass);
26.
27. //测试Object.getClass()
28.
29. TestClassType testGetClass= new TestClassType();
30.
31. System.out.println("testGetClass---"+testGetClass.getClass());
32.
33.
34.
35. } catch (ClassNotFoundException e) {
36.
37. // TODO Auto-generated catch block
38.
39. e.printStackTrace();
40.
41. }
42.
43.
44.
45. }
46.
47. }
48.
49. class TestClassType{
50.
51. //构造函数
52.
53. public TestClassType(){
54.
55. System.out.println("----构造函数---");
56.
57. }
58.
59. //静态的参数初始化
60.
61. static{
62.
63. System.out.println("---静态的参数初始化---");
64.
65. }
66.
67. //非静态的参数初始化
68.
69. {
70.
71. System.out.println("----非静态的参数初始化---");
72.
73. }
74.
75. }
测试的结果如下:
---静态的参数初始化---
testForName---class TestClassType
testTypeClass---class TestClassType
----非静态的参数初始化---
----构造函数---
testGetClass---class TestClassType
根据结果可以发现,三种生成的Class对象一样的。并且三种生成Class对象只打印一次“静态的参数初始化”。
我们知道,静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。
因此,这段程序说明,三种方式生成Class对象,其实只有一个Class对象。在生成Class对象的时候,首先判断内存中是否已经加载。
所以,生成Class对象的过程其实是如此的:
当我们编写一个新的java类时,JVM就会帮我们编译成class对象,存放在同名的.class文件中。在运行时,当需要生成这个类的对象,JVM就会检查此类是否已经装载内存中。若是没有装载,则把.class文件装入到内存中。若是装载,则根据class文件生成实例对象。