首页 > 其他分享 >类加载和通过反射获取类的结构信息

类加载和通过反射获取类的结构信息

时间:2023-05-23 12:03:44浏览次数:33  
标签:反射 System public 获取 println out Class 加载

1. 基本说明  719

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

1.静态加载:编译时加载相关的类,如果没有写出该类,则报错,依赖性太强

2.动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,也不报错,降低了依赖性

代码在com.stulzl.class_load_.包中

ClassLoad_

package com.stulzl.class_load_;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

//类加载  719
public class ClassLoad_ {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入key");
        String key = scanner.next();
        switch(key){
            case "1":
                Dog dog = new Dog();//静态加载,依赖性很强,因为静态加载,所以必须写出Dog类,编译才能通过
                dog.cry();
                break;
            case "2":
                //反射->动态加载,不用写出这个类编译就能通过
                Class cls = Class.forName("com.stulzl.class_load_.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……");
        }
    }
}
//因为new Dog()是静态加载,因此必须编写Dog
//Person类是动态加载,所以,没有编写Person类也不会报错,只要有当动态加载该类时才会报错
class Dog{
    public void cry(){
        System.out.println("小狗汪汪叫……");
    }
}

class Person{
    public void hi(){
        System.out.println("小孩打招呼……");
    }
}

2. 类加载时机  719

1.当创建对象时(new) //静态加载

2.当子类被加载时,父类也加载//静态加载

3.调用类中的静态成员时//静态加载

4.通过反射//动态加载  例:Class.forName(" com.test.Cat"):

3. 类加载过程图  720

类加载和通过反射获取类的结构信息_java

4. 类加载各阶段完成任务  720

类加载和通过反射获取类的结构信息_java_02

4.1 加载阶段  721

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

类加载和通过反射获取类的结构信息_java_03

4.2 连接阶段-验证  721

1.目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证、字节码验证和符号引用验证

3. 可以考虑使用-Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。

4.3 连接阶段-准备  721

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

2.举例说明: ClassLoad02.java

代码在com.stulzl.class_load_02.

 ClassLoad02

package com.stulzl.class_load_02;

//我们说明一下列加载的链接阶段——准备  721
public class ClassLoad02 {
    public static void main(String[] args) {

    }
}
class A{
    //属性-成员变量-字段
    //分析类加载的链接阶段-准备 属性是如何处理
    //1. n1 是实例属性, 不是静态变量,因此在准备阶段,是不会分配内存
    //2. n2 是静态变量,分配内存 n2 是默认初始化 0 ,而不是 20
    //3. n3 是 static final 是常量, 他和静态变量不一样, 因为一旦赋值就不变 n3 = 30
    public int n1 = 10;
    public static int n2 = 20;
    public static final int n3 = 30;//提示final修饰的变量不允许被修改
}

4.4 连接阶段-解析  721

1.虚拟机将常量池内的符号引用替换为直接引用的过程。

2.举例说明:

类加载和通过反射获取类的结构信息_System_04

4.5 Initialization(初始化)  722

1.到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行< clinit> 0方法的过程。

2.  ()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,井进行合井。[举例说明ClassLoad03.java]

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

代码在com.stulzl.class_load_03

ClassLoad03

package com.stulzl.class_load_03;

//演示类加载-初始化阶段  722
public class ClassLoad03 {
    public static void main(String[] args) {

        //分析
        //1. 加载 B 类,并生成 B 的 class 对象
        //2. 链接——赋默认值 num = 0
        //3. 初始化阶段
        // 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
        /*
            clinit() {
                System.out.println("B 静态代码块被执行");
                num = 300;
                num = 100;
            }
            合并结果: num = 100
        */
        //new B();//类加载
        System.out.println(B.num);//100//如果直接使用类的静态属性,也会导致类的加载

        //看看加载类的时候,是有同步机制控制
        /*
        protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
        {
            //正因为有这个机制,才能保证某个类在内存中, 只有一份 Class 对象
            synchronized (getClassLoadingLock(name)) {
            //.... }
        }
        */
        B b = new B();
    }
}
class B {
    //代码块
    static {
        System.out.println("B 静态代码块被执行");
        num = 300;
    }
    static int num = 100;
    public B() {//构造器
        System.out.println("B() 构造器被执行");
    }
}

5. 通过反射获取类的结构信息

5.1 第一组: java.lang.Class 类     723

1. getName:获取全类名

2. getSimpleName:获取简单类名

3. getFields:获取所有public修饰的属性,包含本类以及父类的

4. getDeclaredFields:获取本类中所有属性

5. getMethods:获取所有public修饰的方法,包含本类以及父类的

6. getDeclaredMethods:获取本类中所有方法

7. getConstructors: 获取本类所有public修饰的构造器

8. getDeclaredConstructors:获取本类中所有构造器

9. getPackage:以Package形式返回包信息

10.getSuperClass:以Class形式返回父类信息

11.getInterfaces:以Class[]形式返回接口信息

12.getAnnotations:以Annotation[]形式返回注解信息

代码在com.stulzl.reflection_.包中

ReflectionUtils

package com.stulzl.reflection_;

import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//演示如何通过反射获取列的结构信息  723
public class ReflectionUtils {
    public static void main(String[] args) {

    }
    //第一组
    @Test
    public void api_01() throws ClassNotFoundException {
        Class personCls = Class.forName("com.stulzl.reflection_.Person");
        //1. getName:获取全类名
        System.out.println(personCls.getName());//com.stulzl.reflection_.Person

        //2. getSimpleName:获取简单类名
        System.out.println(personCls.getSimpleName());//Person

        //3. getFields:获取所有public修饰的属性,包含本类以及父类的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {//增强for循环
            System.out.println("本类以及父类的public属性"+field.getName());
        }

        //4. getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有属性"+declaredField.getName());
        }

        //5. getMethods:获取所有public修饰的方法,包含本类以及父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本类以及父类的public方法"+method.getName());
        }

        //6. getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法"+declaredMethod.getName());
        }

        //7. getConstructors: 获取本类所有public修饰的构造器
        Constructor[] constructors = personCls.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("本类所有public修饰的构造器"+constructor);
        }

        //8. getDeclaredConstructors:获取本类中所有构造器
        Constructor[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("获取本类中所有构造器"+ declaredConstructor);
        }

        //9. getPackage:以Package形式返回包信息
        System.out.println(personCls.getPackage());//com.stulzl.reflection_

        //10.getSuperClass:以Class形式返回父类信息
        Class superclass = personCls.getSuperclass();
        System.out.println(superclass);//com.stulzl.reflection_.A

        //11.getInterfaces:以Class[]形式返回接口信息
        Class[] interfaces = personCls.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println("接口信息"+anInterface);
        }

        //12.getAnnotations:以Annotation[]形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解"+annotation);
        }

    }
}

class A{
    public String hobby;
    public void hi(){

    }
    //构造器
    public A(){}

}
interface IA{

}
interface IB{

}

@Deprecated  //注解
class Person extends A implements IA,IB{
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;

    //构造器
    public Person(){}
    public Person(String name){}
    private Person(String name,int age){}

    //方法
    public void m1(){

    }

    protected void m2(){

    }

    void m3(){

    }

    private void m4(){

    }
}

5.2 第二组: java.lang.reflect.Field 类  724

1. getModifiers: 以int形式返回修饰符[说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final 是16],public(1) + static (8) = 9

2. getType:以Class形式返回类型

3. getName:返回属性名

5.3 第三组: java.lang.reflect.Method 类  724

1. getModifiers:以int形式返回修饰符[说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final是16]

2. getReturnType:以Class形式获取返回类型

3. getName:返回方法名

4. getParameterTypes:以Class[]返回参数类型数组

5.4 第四组: java.lang.reflect.Constructor 类  724

1. getModifiers:以int形式返回修饰符

2. getName:返回构造器名(全类名)

3. getParameterTypes:以Class[]返回参数类型数组

二三四组代码在com.stulzl.reflection_02

ReflectionUtils02

package com.stulzl.reflection_02;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//通过反射获取类的结构信息
public class ReflectionUtils02 {
    public static void main(String[] args) {

    }

    @Test
    public void api_02() throws ClassNotFoundException {
        Class personCls = Class.forName("com.stulzl.reflection_02.Person");

        //第二组: java.lang.reflect.Field 类    724
        //4. getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有属性"+declaredField.getName()
                    //1. getModifiers: 以int形式返回修饰符[说明:默认修饰符是0,public 是1,
                    // private是2,protected是4,static是8,final 是16]
                    +" 该属性的修饰符="+declaredField.getModifiers()
                    //2. getType:以Class形式返回类型
            +" 给属性的类型="+declaredField.getType());
        }
        System.out.println("=========================");
        //第三组: java.lang.reflect.Method 类  724
        //6. getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法"+declaredMethod.getName()
                    //1. getModifiers:以int形式返回修饰符[说明:默认修饰符是0,public 是1,
                    // private是2,protected是4,static是8,final是16]
            +" 该方法的访问修饰符="+declaredMethod.getModifiers()
                    //2. getReturnType:以Class形式获取返回类型
            +" 该方法的返回类型="+declaredMethod.getReturnType());

            //4. getParameterTypes:以Class[]返回参数类型数组
            Class[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println("该方法的形参数组="+parameterType);
            }
        }
        System.out.println("===============");
        //第四组: java.lang.reflect.Constructor 类   724
        //8. getDeclaredConstructors:获取本类中所有构造器
        Constructor[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("获取本类中所有构造器"+ declaredConstructor);

            //3. getParameterTypes:以Class[]返回参数类型数组
            Class[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println("该构造器的形参数组="+parameterType);
            }
        }
    }
}
class A{
    public String hobby;
    public void hi(){

    }
    //构造器
    public A(){}

}
interface IA{

}
interface IB{

}

@Deprecated  //注解
class Person extends A implements IA, IB {
    //属性
    public String name;
    protected static int age;//修饰符值4(protected)+8(static)=12
    String job;
    private  double sal;

    //构造器
    public Person(){}
    public Person(String name){}
    private Person(String name,int age){}

    //方法
    public void m1(String name,int age,double sal){

    }

    protected String m2(){
        return null;
    }

    void m3(){

    }

    private void m4(){

    }
}

标签:反射,System,public,获取,println,out,Class,加载
From: https://blog.51cto.com/u_15784725/6330517

相关文章

  • Js获取当前是本年度第几周、周开始日期结束日期
    js获取今年第几周和获取周的开始和结束日期获取今年第几周周的开始和结束日期 获取今年第几周//页面初始时获取当前是本年第几周functiongetYearWeek(a,b,c){//a为年b为月c为日/*date1是当前日期date2是当年第一天......
  • 获取当前页真实链接
    importrequestsdefrequest_zy(url):response=requests.get(url=url)returnresponse.urlif__name__=='__main__':url='http://www.baidu.com/link?url=N4eynVHBVTmN6ikAQKABNbAhT-YqKIyQYnedOewWz3k3hm341LgiUcWX6Tpw-R2iOqLyf9Ox05OYnrdY......
  • 获取下一个月日期
    publicstaticfinalStringgetNextMonth(StringqueryMonth)throwsParseException{SimpleDateFormatformat=newSimpleDateFormat("yyyy-MM");Calendarcalendar=Calendar.getInstance();//设置为当前时间DateFormatdateFormat=newSimpleDa......
  • JWT加签从密钥库获取密钥对完成对JWT的签名,密钥库生成步骤
    ​ 最近再用jwt生成token,记录一下使用jdk生成秘钥库步骤,方便之后查询使用1、生成密钥库脚本命令(在本地jdk目录bin目录下,窗口路径输入cmd会车)keytool-genkey-aliasjwt-keyalgRSA-keypass123456-keystorejwt.jks-storepass123456参数说明:-alias别名-keyalg密......
  • 解决启动jar包报错:错误找不到或无法加载主类 jar
    错误:找不到或无法加载主类jar问题描述:在使用springboot框架对项目打包后,手动使用命令java-jar包名启动jar包,报错:错误:找不到或无法加载主类jar。网上找了各办法,都是加maven插件,打成可执行jar包<build><plugins><plugin><groupId>org.springframework.bo......
  • 如何在EasyCVR视频融合平台通过接口获取告警的录像以及快照?
    EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。为了便于用户二次开发、集成与调用,我们也提供了丰富的API接......
  • 前端框架中加入外部config可配置文件,根据不同的运行、编译环境,加载不同的配置文件
    需求:我们的乾坤vue框架,需要集成给第三方,menu由他们处理(包括菜单权限),我们只负责提供一个去除menu和头部的main即可;这里需要可配置,不能把我们的menu弄丢了。实现方式:1、在src同级目录新建public/plugins/config.js因为是基于webpack打包,会自动过滤public下的文件,复制到打包后的......
  • 获取当前时间戳
    #include<stdio.h>#include<stdlib.h>#define_POSIX_C_SOURCE200112L//forsetenvongcc#include<stdlib.h>#include<stdio.h>#include<time.h>intmain(void){time_tt=time(NULL);structtm*tm=loca......
  • java基于joda-date实现获取两个时间段对应类型的所有时间,比如说两年之间的所有日期,两
    /***获取两个时间段对应类型的所有时间**@paramtype日期类型,包含day、month、year*@parambeginTime开始时间*@paramendTime结束时间*@return*/publicstaticList<String>getBetweenTime(Stringtype,String......
  • 纯CSS实现加载效果
    HTML标签<divclass="loading"><span></span><span></span><span></span><span></span><span></span></div>CSS样式<style>.loading{ width:80px; height:40px; ......