美文网首页
Java反射中获取Class对象三种方式的区别

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

作者: 倚仗听江 | 来源:发表于2020-09-05 14:44 被阅读0次

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

    • new Object().getClass
    • Object.class
    • Class.forName("com.sherlock.demo")

    以下就详细的讲讲这三种方式的区别
    首先我们先定义一个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();
        }
    }
    
    • 第一种方式下,没有任何的输出,说明通过Demo.class获取对象的Class对象,不会调用任何的代码块和代码。
    • 第二种方式下,会打印:Demo:静态代码块,说明在这种方式下会调用静态代码块的内容。
    • 第三种方式下,会打印:Demo:静态代码块
      Demo:动态代码块
      Demo:构造方法
      也就是说,在这种方式下,因为要先实例化对象,所以会打印全部的内容。

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

    @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/

    相关文章

      网友评论

          本文标题:Java反射中获取Class对象三种方式的区别

          本文链接:https://www.haomeiwen.com/subject/ppffektx.html