zoukankan      html  css  js  c++  java
  • java反射

    一、类的加载连接初始化

    1)JVM和类

      当我们调用java命令运行某个java程序时,该命令将会启动一个java虚拟机进程,该程序启动的多个线程,都处于该java虚拟机进程,当系统出现一下几种情况,JVM进程终止

        1.程序运行到最后正常结束

        2.程序运行到使用System.exit()或Runtime.getRuntime().exit代码处结束程序

        3.程序执行过程中,遇到未捕获的异常或错误而接受

        4.程序所在平台强制结束了JVM进程

    2)类的加载

      当程序主动使用某个类,如果该类还未加载到内存,则系统会通过加载连接初始化3个步骤对该类进行初始化。(将类的class文件读入内存,并为之创建一个java.lang.Class对象)

      类的加载由类加载器来完成,类加载器通常由JVM提供,JVM所提供的这些类加载器称为系统类加载器,也可以通过继承ClassLoader基类来创建自己的类加载器。

      通过使用不同的类加载器 ,可以从不同来源加载类的二进制数据,通常有以下几种来源。

      1.从本地文件系统加载class文件,

      2.从JAR包加载class文件,如JDBC

      3.通过网络加载class文件

      4.把一个java源文件动态编译,并执行加载

      java虚拟机允许预先加载类,而不用等到首次使用该类时才进行加载

    3)类的连接

      当类被加载之后,系统为之生成一个对应的Class文件,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JAR中,类的连接又分为

      1.验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致

      2.准备:类准备阶段负责为类的静态FIeld分配内存,并设置默认初始值

      3.解析:将类的二进制数据中的符号引用替换成直接引用

    4)初始化

      在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对静态Field进行初始化。

    5)类的初始化时机

      1.创建类的实例,包括:new,反射,反序列化

      2.调用某个类的静态方法

      3.访问某个类或接口的静态Field,或为该静态Field赋值

      4.使用反射强制创建某个类或接口对应的java.lang.Class对象,例如:Class.forName("Person"),如果系统还未初始化Person类,则会进行初始化

      5.初始化某个类的子类,其所有父类都会进行初始化

      6.直接使用java.exe命令允许某个主类

      注意:对于一个Final 静态变量,如果该Field的值在编译时就确定下来,那么这个相当于宏变量,java编译器会在编译时直接把出现该Field的地方替换为值,因此程序使用该静态Field也不会初始化该类

      如果该值不能在编译时确定下来,则会引起初始化。

    二、类加载器

      1)类加载器简介

      类加载器负责将.class文件(可能在磁盘,也可能在网络)加载到内存中,并为之生成对应的java.lang.Class对象。

      一旦一个类被加载到内存,同一个类就不会被再次载入了。在java中,一个类使用全限定名称作为标指,但在JVM中,一个类使用其全限定名称和其类加载器作为唯一标指(用来判断是否是同一个类)

      当JVM启动时,会形成3个类加载器组成的初始类加载器层次结构

      1.Bootstrap ClassLoader:根类加载器

      2.Extension ClassLoader:扩展类加载器

      3.System ClassLoader:系统类加载器

      Bootstrap ClassLoader被称为引导类加载器,它负责加载java核心类,在sun的JAM中,当执行java.exe命令时,使用-Xbootclasspath选项或使用-D选项指定sun.boot.class.path系统属性值可以指定加载附加的类,根类加载器非常特殊,它并不是java.lang.ClassLoader类的子类,而是JVM自身实现。

      2)类的加载机制

      JVM类加载机制主要有以下三种

      1.全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器

      2.父类委托:先让父类加载器试图加载该Class,只有在父类加载器无法加载时,才尝试从自己的类路径中加载该类

      3.缓存机制:缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类的二进制数据,并将其转换成Class对象,存入缓存区中,这就是为什么修改Class后,必须重新起点JVM,程序所做的修改才会生效。

      类加载器层次结构:根类加载器<—扩展类加载器<—系统类加载器<—用户类加载器

    三、反射

       有时,程序在运行时,接收到外部传入的一个对象,该对象在编译时类型是Object,但程序又需要调用该对象运行时类型的方法。

    1)获得Class对象

       上面已经介绍过,每个类被加载之后,系统就会为该类生成一个对应的Class对象,则通过该Class对象就可以访问到JVM中对应的类

        1.使用Class类的forName(String clazzName)静态方法,该方法传入某个类的全限定名称

        2.调用某个类的class属性获取该类的Class对象

        3.调用某个对象的getClass方法,该方法时java.lang.Object的一个方法,

      相比之下,第二种方式有以下优点:1.代码更安全,程序在编译阶段就可以检查要访问的Class对象是否存在  2.程序性能更好,因为这种方式无需调用方法

      使用第一种方法,该方法会抛出一个ClassNotFoundException异常

    2)从Class中获取信息

      

    3)使用反射生成并操作对象

    1.创建对象

      有两种方式

      1.1使用Class对象的neInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法实质是利用默认构造器来创建该类的实例。

      1.2先使用Class对象获取指定Constructor对象,在调用Constructo对象的newInstance()方法来创建该Class对象对应类的实例,通过这种方式可以选择使用指定构造器来创建。

     

     

  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/UalBlog/p/10662423.html
Copyright © 2011-2022 走看看