zoukankan      html  css  js  c++  java
  • java两种反射的区别

    在理解这两种反射机制之前,需要弄清楚java类的加载机制.

    装载:通过类的全限定名获取二进制字节流(二进制的class文件),将二进制字节流转换成方法区中的运行时数据结构,在内存中生成Java.lang.class对象。这个时候该类型没有被分配内存,设置默认值,也没有初始化。

    链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;

      校验:检查导入类或接口的二进制数据的正确性;(文件格式验证,元数据验证,字节码验证,符号引用验证)

      准备:给类的静态变量分配并初始化存储空间;

      解析:将常量池中的符号引用转成直接引用;

    初始化:激活类的静态变量的初始化Java代码和静态Java代码块,并初始化程序员设置的变量值。

    Class.forName有两个重载方法:

     public static Class<?> forName(String name, boolean initialize,
                       ClassLoader loader)
            throws ClassNotFoundException
    
    
     public static Class<?> forName(String className) 
                    throws ClassNotFoundException

    解释:

    name:类的全限定名,如:com.org.prj
    initialize:如果为true,则会在返回Class对象之前,对该类型做连接,校验,初始化操作。(如:执行static块中的代码),initialize默认需要初始化。
    loader:用自定义的类加载器来请求这个类型;当然,你也可以传入null,用bootstrap加载器

    由于Class.forName默认是需要初始化,一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。

    我们在来看ClassLoader.loadClass也有两个两个重载方法:

    protected synchronized Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    
    public Class<?> loadClass(String name) throws ClassNotFoundException 

    解释:

    name:类的全限定名,如:com.org.prj

    resolve:表示是否需要连接该类型。 仅仅是连接(这里面包括校验class文件,准备分配内存,类型常量池的替换),并不会初始化该类型。

    resolve默认是不链接,不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行。

    总结:

    1.Class.forName返回的Class对象可以决定是否初始化。而ClassLoader.loadClass返回的类型绝对不会初始化,最多只会做连接操作。
    2.Class.forName可以决定由哪个classLoader来请求这个类型。而ClassLoader.loadClass是用当前的classLoader去请求。

  • 相关阅读:
    Chrome使用指南
    Vue2.x-踩坑记
    C# WinForm listView 多行删除 操作
    Winform中DataGridView多行删除
    20211026_阿里云服务器引流限制ssl的问题
    docker commit
    docker build
    docker build与docker commit
    阿里云Docker镜像仓库(Docker Registry)
    Docker Nginx安装(centos7)
  • 原文地址:https://www.cnblogs.com/clarke157/p/6651195.html
Copyright © 2011-2022 走看看