首页 > 其他分享 >反射 p3 类加载

反射 p3 类加载

时间:2023-07-25 18:22:55浏览次数:38  
标签:p3 java 反射 静态 Dog ClassLoad public 加载

类加载

基本说明

反射机制是Java实现动态语言的关键,也就是通过反射实现类动态加载。

  1. 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强。
  2. 动态加载:运行时加载相关的类,如果运行时不用该类,即使不存在该类,也不会报错,降低了依赖性。
  • 代码演示:

    import java.util.*;
    import java.lang.reflect.*;
    
    public class ClassLoad_{
    	public static void main(String[] args) throws Exception{
    		Scanner scan = new Scanner(System.in);
    		String key = scan.next();
    
    		switch(key){
    			case "1":
    				Dog dog = new Dog();//静态加载,依赖性很强
    				dog.cry();
    				break;
    			case "2":
    				//反射 -> 动态加载
    				Class cls = Class.forName("Person");//加载Person类[动态加载]
    				Object o = cls.newInstance();
    				Method m = cls.getMethod("hi");
    				m.invoke(o);
    				System.out.println("OK");
    				break;
    			default:
    				System.out.println("do nothing....");
    		}
    
    	}
    }
    
    
    /* 未写Dog类时,DOS窗口运行结果,编译错误
    C:\Users\86199\Desktop>javac ClassLoad_.java
    ClassLoad_.java:11: 错误: 找不到符号
                                    Dog dog = new Dog();//静态加载,依赖性很强
                                    ^
      符号:   类 Dog
      位置: 类 ClassLoad_
    ClassLoad_.java:11: 错误: 找不到符号
                                    Dog dog = new Dog();//静态加载,依赖性很强
                                                  ^
      符号:   类 Dog
      位置: 类 ClassLoad_
    注: ClassLoad_.java使用了未经检查或不安全的操作。
    注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
    2 个错误
    */
    
    
    //因为 new Dog() 是静态加载,因此必须编写Dog类,否则在编译过程就会报错
    //Person类是动态加载,所以没有编写Person类在编译过程也不会报错,
    //只有在动态加载该类时才会报错
    
    class Dog{
    	public void cry(){
    		System.out.println("小狗汪汪叫");
    	}
    }
    
    
    /* 未写Person类时,DOS窗口运行结果,运行时报错
    C:\Users\86199\Desktop>java ClassLoad_
    1
    小狗汪汪叫
    ===============================================================
    C:\Users\86199\Desktop>java ClassLoad_
    2
    Exception in thread "main" java.lang.ClassNotFoundException: Person
            at java.net.URLClassLoader.findClass(Unknown Source)
            at java.lang.ClassLoader.loadClass(Unknown Source)
            at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
            at java.lang.ClassLoader.loadClass(Unknown Source)
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Unknown Source)
            at ClassLoad_.main(ClassLoad_.java:16)
    */
    
    
    class Person{
    	public void hi(){
    		System.out.println("hi....");
    	}
    }
    
    /* 写了Peson类后,DOS窗口运行结果
    C:\Users\86199\Desktop>java ClassLoad_
    1
    小狗汪汪叫
    =================================================
    C:\Users\86199\Desktop>java ClassLoad_
    2
    hi....
    OK
    */
    

类加载时机

  1. 当创建对象时(new),静态加载;
  2. 当子类被加载时,父类也加载,静态加载;
  3. 调用类中的静态成员时,静态加载;
  4. 通过反射,动态加载;

类加载流程

类加载流程图

  • 类加载过程图

  • 类加载各阶段完成的任务

类加载五个阶段

  1. 加载阶段(Loading)

    JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象;

  2. 连接阶段(Linking)

    1. 验证(Verification):

      • 目的:是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全;
      • 包括:文件格式验证(是否以魔数 oxcafebabe 开头)、元数据验证、字节码验证和符号引用验证;
      • 可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机加载的时间;
    2. 准备(Preparation):

      JVM 会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配。

      package com.hspedu.classload_;
      
      /**
       * @author: 86199
       * @date: 2023/6/2 21:19
       * @description: 说明类加载夹的连接阶段(Linking)-准备(Preparation)
       */
      public class ClassLoad02 {
      }
      
      class A{
          //属性-字段-成员变量
          //分析类加载阶段的连接阶段(Linking)-准备,属性是如何处理的
          //1. n1是实例属性,不是静态变量,因此在准备阶段是不会分配内存的
          //2. n2是静态属性,分配内存,n2 默认初始化为0,而不是20,20是在连接阶段之后的初始化阶段进行的
          //3. n3是static final 是常量
          public int n1 = 1;
          public static int n2 = 2;
          public final static int n3 = 3;
      }
      
    3. 解析(Resolution):虚拟机将常量池内的符号引用替换为直接引用的过程。

  3. 初始化(Initialization):

    • 到初始化阶段,才是真正的开始执行类中定义的Java程序代码,此阶段是执行()方法的过程;

    • ()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并;

    • 虚拟机会保证一个类的()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都需要阻塞等待,直到活动线程执行()方法完毕;

      源码:

    案例演示:

    package com.hspedu.classload_;
    
    /**
     * @author: 86199
     * @date: 2023/6/2 22:19
     * @description: 演示类加载——初始化阶段(Initialization)
     */
    public class ClassLoad03_ {
        static {
            System.out.println("ClassLoad03_ 静态代码块被执行");
        }
        public static void main(String[] args) throws ClassNotFoundException {
            //1. Loading:加载B类,并生成B类的Class对象
            //2. Linking:num = 0
            //3. Initialization:
            //      依次收集类中所有的静态变量和静态代码块中的语句入clinit()中,并合并
            /*
                clinit(){
                    System.out.println("B 静态代码块被执行");
                    //num = 300;
                    num = 100;
                }
                合并:num = 300, num = 100  --> num = 100
             */
    //        new B();//也会使B类加载,但是B类加载只会执行一遍
    //        System.out.println(B.num);//直接使用B类的静态属性,也会导致B类加载
    
            //看看类加载时,是有同步机制控制的
            /*
                protected Class<?> loadClass(String name, boolean resolve)
                    throws ClassNotFoundException
                {
                    synchronized (getClassLoadingLock(name)) {
                    //拿到一个同步锁,正因为有这个机制,才能保证某个类在内存中只有一份Class对象
                    }
                }
             */
            Class<?> aClass = Class.forName("B");
        }
    }
    
    class B{
        static {
            System.out.println("B 静态代码块被执行");
            num = 300;
        }
    
        static int num = 100;
    
        public B() {//构造器
            System.out.println("B() 构造器被执行...");
        }
    }
    
    

标签:p3,java,反射,静态,Dog,ClassLoad,public,加载
From: https://www.cnblogs.com/zh-Note/p/17557510.html

相关文章

  • 洛谷 P3291 [SCOI2016] 妖怪
    设每只怪物经过环境影响后的攻击力和防守力分别为\(x_i,y_i\),则有:\(y_i=dnf_i-\dfracba(x_i-atk_i)\)。设\(k=-\dfracba\),则有\(y_i=kx_i+dnf_i-k\cdotatk_i\)。设直线\(l_i:y_i=kx_i+dnf_i-k\cdotatk_i\),第\(i\)只怪物在\((a,b)\)的环境下......
  • 洛谷P3629 [APIO2010] 巡逻题解
    题目链接P3629[APIO2010]巡逻-洛谷|计算机科学教育新生态(luogu.com.cn)思路n个村庄,n-1条道路,原图为树1.若k=0(不修建道路)那么答案为(n-1)*2 每个道路会走两遍2.若k为1(修建一条道路)设修建的道路(r1)所在的环长度为L那么答案为(n-1)*2-L+2可以看到r1所在环的道路只走了......
  • Artistdirect.com为Zune播放器提供的热门歌曲MP3
    Artistdirect.com为Zune播放器提供的热门歌曲MP3http://assets.artistdirect.com/Downloads/artd/listen/Smile.mp3http://assets.artistdirect.com/Downloads/artd/listen/cracker-low.mp3http://assets.artistdirect.com/Downloads/artd/listen/DDTS.mp3http://assets.artistdire......
  • luogu P3203 [HNOI2010] 弹飞绵羊 题解
    题目传送门:P3203[HNOI2010]弹飞绵羊题意\(n\)个数,满足\(i<a_i≤N+1\),\(m\)次下面两种操作修改一个数\(a_i\)从\(x\)开始跳,\(x=a_x\),几次能够跳出序列\(n\leq2*10^5,m<10^5\)分析数据范围比较大,单纯搜索模拟肯定会T,那么考虑每次让他跳一段就......
  • GE反射内存卡的指标和型号
    产品特性:•1路发送,1路接收;•光纤高速网络2.12GHz;•最大256个节点;•光纤协议不占用CPU资源;•多模光纤节点距离300米;单模光纤节点距离10千米;•板载128M/256MByteSDRAM;•低延迟率(n秒级);•动态包长:每个包4到64或1M个字节。产品选型:1、CPCI接口-5565PIORC-110000(128MSDRAM多......
  • Java-Day-35( 类加载 + 细化解释各阶段 )
    Java-Day-35类加载基本说明反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载静态加载:编译时加载相关的类,如果没有则报错,依赖性太强在非具备idea辅助型的工具里编写代码时importjava.util.Scanner;publicclasstest{publicstaticvoidmain(......
  • Java-Day-36( 通过反射获取类的结构信息 + 通过反射访问类中的成员 + 章节练习 )
    Java-Day-36通过反射获取类的结构信息第一组:java.lang.Class类以下说的包含本类和父类——也包括超类等方法属性之类的若是输出时不加.getName,则都是输出:com.zyz.Zyz()publicclasstest{publicstaticvoidmain(String[]args){}@Testpubl......
  • cocos creator 资源加载函数 resources.load 注意该函数为异步
    constanimationComponent=i.addComponent(Animation);if(animationComponent){constcomponent=animationComponent.getComponent(Animation);if(component){resources.load("An......
  • Java类加载
    Java类加载类加载过程加载:JVM将class文件加载到内存中,并生成class对象连接(验证、准备、解析):JVM校验class对象的规范性等初始化:JVM执行class对象中的静态代码块的语句和对静态变量的赋值操作使用:创建实例化对象、调用方法等卸载:类加载机制类加载源码protectedClass<?>lo......
  • 类加载及字节码
    Class类文件的结构Class文件是一组以8个字节为基础单位的二进制流,各数据严格按照顺序紧凑排列在文件中Class文件采用一种伪结构来存储数据,伪结构中只有两种数据类型无符号数:基本数据类型,以u1/u2/u4/u8分别代表1/2/4/8个字节的无符号数,无符号数可以用来描述数字、索引引用、数......