java中获取Class对象的三种方式和区别

Class对象的生成方式如下:

 

1.类名.class 说明:JVM将使用类装载器, 将类装入内存(前提是:类还没有装入内存),不做类的初始化工作.返回Class的对象

 

2.Class.forName("类名字符串")(注:类名字符串是包名+类名) 说明:装入类,并做类的静态初始化,返回Class的对象

 

3.实例对象.getClass() 说明:对类进行静态初始化、非静态初始化;返回引用运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象

 

通过下面的程序,来观察一下Class对象的生成的原理。
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package ClassTest; 
   
public class TestClass { 
    public static void main(String[] args) { 
   
        try
            // 测试.class 
            @SuppressWarnings("rawtypes"
            Class testTypeClass = TestClassType.class
            System.out.println("testTypeClass---" + testTypeClass); 
   
            // 测试Class.forName() 
            @SuppressWarnings("rawtypes"
            Class testTypeForName = Class.forName("ClassTest.TestClassType"); 
            System.out.println("testTypeForName---" + testTypeForName); 
   
            // 测试Object.getClass() 
            TestClassType testTypeGetClass =new TestClassType(); 
            System.out.println("testTypeGetClass---" 
                    + testTypeGetClass.getClass()); 
   
        }catch (ClassNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        
    
   
}
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package ClassTest; 
   
public class  TestClassType { 
   
    // 构造函数 
    public TestClassType() { 
        System.out.println("----构造函数---"); 
    
   
    // 静态的参数初始化 
    static
        System.out.println("---静态的参数初始化---"); 
    
   
    // 非静态的参数初始化 
    
        System.out.println("----非静态的参数初始化---"); 
    
   
}
运行结果如下:
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
testTypeClass---class ClassTest.TestClassType 
---静态的参数初始化--- 
testTypeForName---class ClassTest.TestClassType 
----非静态的参数初始化--- 
----构造函数--- 
testTypeGetClass---class ClassTest.TestClassType
    根据结果可以发现,三种生成的Class对象一样的。并且程序只打印一次“静态的参数初始化”。

 

    我们知道,静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。

 

    因此,这段程序说明,三种方式生成Class对象,其实只有一个Class对象。在生成Class对象的时候,首先判断内存中是否已经加载。

 

    所以,生成Class对象的过程其实是如此的:

 

    当我们编写一个新的java类时,JVM就会帮我们编译成class对象,存放在同名的.class文件中。在运行时,当需要生成这个类的对象,JVM就会检查此类是否已经装载内存中。若是没有装载,则把.class文件装入到内存中。若是装载,则根据class文件生成实例对象。



int.class 与 Integer.class的区别?

今天在看JDK中Integer.java的源码时,发现Integer.TYPE这么一个东西,

 

[Java] 纯文本查看 复制代码
1
<font style="color:rgb(77, 77, 77)"><font face="&quot"><font style="font-size:16px">public static final Class TYPE = (Class ) Class.getPrimitiveClass("int");</font></font></font>

 

根据JDK文档的描述,Class.getPrimitiveClass("int") 方法返回的是int类型的Class对象,可能很多人会疑惑,int不是基本数据类型吗?为什么还有Class对象啊?

然后在网上搜寻一番之后,总结一下搜寻的结果:

    有9个预先定义好的Class对象代表8个基本类型和void,它们被java虚拟机创建,和基本类型有相同的名字boolean, byte, char, short, int, long, float, and double.
    这8个基本类型的Class对象可以通过java.lang.Boolean.TYPE,java.lang.Integer.TYPE等来访问,同样可以通过int.class,boolean.class等来访问.
int.class与Integer.TYPE是等价的,但是与Integer.class是不相等的,int.class指的是int的Class对象,Integer.class是Integer的Class的类对象. 

 

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
public class IntClasses {
public static void main(String[] args) {
Class a =int.class;
Class b = Integer.TYPE;
Class c = Integer.class;
System.out.println(System.identityHashCode(a));
System.out.println(System.identityHashCode(b));
System.out.println(System.identityHashCode(c));
}
}


运行结果为

[Java] 纯文本查看 复制代码
1
2
3
366712642
366712642
1829164700


通过结果可以知道 第1,2行输出永远相等,并且和第3行的输出不同.


版权声明:本文为heima201907原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。