18-Java反射

类加载器

作用:将编译的.class文件加载进入jvm

Bootstrap ClassLoader 根类加载器

作用: 加载JDK、JRE的核心类:System、String

Extension ClassLoader 扩展类加载器

作用:负责jre-lib目录下的jar包或资源文件的加载

System ClassLoader 系统类加载器

作用:负责在JVM启动时加载来及java或javac的加载命令

一个.class文件只会对应一个字节码文件对象(Class类对象)

一个类的不同对象,也只会拥有同一个字节码文件对象

Class对象获取的三种方法

// 加载的字节码文件不存在项目路径中时(不是自己写的)
        Class<?> aClass = Class.forName("com.huawei.java.wx.WXClient");

        // 加载时该类只是被类加载器加载但是没有对象时
        Class<WXClient> wxClientClass = WXClient.class;

        // 已经有对象,但是要反推得到对应类的字节码文件对象
        WXClient c1 = new WXClient("11");
        Class<? extends WXClient> aClass1 = c1.getClass();

反射-Class对象三个重要对象

Field 对象- 类的属性对象

获取所有字段的方法:

1.得到类的所有public字段
Field[] getFields() 

2. 返回类中所有的字段,包括:私、保、默、公
Field[] getDeclaredFields()   
获取指定字段的方法:

1.获取某个"公有的"字段:
public Field getField(String fieldName)2.获取某个字段(可以是私有的) 
public Field getDeclaredField(String fieldName)


获取变量的类型:
Field.getType():返回这个变量的类型
Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回 Field.getType()
isEnumConstant() : 判断这个属性是否是枚举类
获取成员变量的修饰符
       Field.getModifiers()  以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符
* private static final 2+8+16 = 26
         *
         * private : 2
         * (default):0
         * protected4
         * public : 1
         * static : 8
         * final : 16
获取和修改成员变量的值
getName() : 获取属性的名字
get(Object obj) 返回指定对象obj上此 Field 表示的字段的值
set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值

jdk8以上版本,想要危险操作时添加

JDK制作的库(JDK8及以下)运行在JDK9上会自动被标识为未命名模块,为了处理该警告,JDK9以上提出了一个新的JVM参数:--illegal-access。

该参数有四个可选值:
1.permit:默认值,允许通过反射访问,因此会提示像上面一样的警告,这个是首次非法访问警告,后续不警告
2.warn:每次非法访问都会警告
3.debug:在warn的基础上加入了类似e.printStackTrace()的功能
4.deny:禁止所有的非法访问除了使用特别的命令行参数排除的模块,比如使用--add-opens排除某些模块使其能够通过非法反射访问
因此解决的办法很简单,将其设置为deny,并添加--add-opens开启对应的允许非法反射访问的模块即可。

--illegal-access=deny --add-opens java.base/java.lang=ALL-UNNAMED

add-opens可以使模块中的包对其他模块开放,这样就可以在运行期使用深层反射访问该程序包中的所有成员类型。


猜你喜欢

转载自blog.csdn.net/gjb760662328/article/details/129164501