Java反射中获取Class对象三种方式的区别

2020-09-05  本文已影响0人  倚仗听江

Java反射中获取Class有三种方式:

以下就详细的讲讲这三种方式的区别
首先我们先定义一个Demo类,其中定义了静态代码块、动态代码块和构造函数

public class Demo {
    static {
        System.out.println("Demo:静态代码块");
    }
    {
        System.out.println("Demo:动态代码块");
    }
    public Demo(){
        System.out.println("Demo:构造方法");
    }
}

分别对这三种场景进行测试

public class Test {
    @org.junit.jupiter.api.Test
    public void test1(){
        Class<?> clz = Demo.class;
    }

    @org.junit.jupiter.api.Test
    public void test2() throws ClassNotFoundException {
        Class<?> clz = Class.forName("com.sherlock.Demo");
    }
    @org.junit.jupiter.api.Test
    public void test3() {
        Class<?> clz = new Demo().getClass();
    }
}

接下来我们同时使用这三种方式

@org.junit.jupiter.api.Test
    public void test4() throws ClassNotFoundException {
        Class<?> clz = Demo.class;
        System.out.println("---------------");
        clz = Class.forName("com.sherlock.Demo");
        System.out.println("---------------");
        clz = new Demo().getClass();
    }

打印结果


打印结果.jpg

使用Demo.class还是和上面一样,不会调用任何的代码或代码块。使用Class.forName("com.sherlock.Demo")会调用静态代码块。但是在使用new Demo().getClass()时,却没有再次调用静态代码块,说明了静态代码块只会被初始化一次。

再来比较一下这三种情况下获得的对象是不是同一个

@org.junit.jupiter.api.Test
    public void test6() throws ClassNotFoundException {
        Class<?> clz1 = Demo.class;
        Class<?> clz2 = Class.forName("com.sherlock.Demo");
        Class<?> clz3 = new Demo().getClass();
        System.out.println(clz1 == clz2);
        System.out.println(clz2 == clz3);
    }

可以发现比较的结果都是true,说明获取的是同一个对象。这是因为对于同一个Classloader对象,不管某个类被加载多少次,对应堆内存中的class对象始终只有一个。也就是说无论通过哪种形式来获取Class对象,获得的都是堆内存中对应的Class对象

总结一下:
(1)类名.class:JVM将使用类装载器,将类装入内存(前提是:类还没有装入内存),不做类的初始化工作,返回Class的对象。
(2)Class.forName(“类的全限定名”):装入类,并做类的静态初始化,返回Class的对象。
(3)实例对象.getClass():对类进行静态初始化、非静态初始化;返回引用运行时真正所指的对象(子对象的引用会赋给父对象的引用变量中)所属的类的Class的对象。

原文链接:https://www.choupangxia.com/2020/03/27/java-reflect-class/

上一篇 下一篇

猜你喜欢

热点阅读