• Java反射


    什么是反射

    运行时动态获取对象的全部类型信息

    反射原理-Class类 + 类加载

    在markword中保存有对象的类型指针,这个指针会指向Class对象,这个对象保存了类型信息,就是类加载的时候会将对应的类型定义读入到内存中,markword的类型指针会指向这个类的类型定义。

    在这里插入图片描述

    所以可以通过.class来获取对象的类型信息,然后通过Class来进行保存,访问对应的类。

    另外加载是动态加载的,不是静态加载的。不是一次性将所有的class读入到内存中,而是在发现缺少某一个class的时候,再把对应的类型定义读入到内存中。

    反射的常用接口

    获取类 + 创建对象

    1. .classs
    2. .getClass
    3. Class.forName(“全类名”);
    4. class.newInstance();

    访问方法

    1. getMethod(name,参数类型)。通过invoke(对象,参数)进行调用,静态方法使用invoke(null, 参数)
    2. 非public方法,使用setAccessible(true);调用
    3. 仍旧遵循堕胎原则

    获取字段

    1. Field getField(name):根据字段名获取某个 public 的 field(包括父类)
    2. Field getDeclaredField(name):根据字段名获取当前类的某个 field(不包括父类)
    3. Field[] getFields():获取所有 public 的 field(包括父类)
    4. Field[] getDeclaredFields():获取当前类的所有 field(不包括父类)

    父类的字段无法继承,如果想要获取父类的方法,需要通过不加declared进行访问。

    反射的安全性

    由于可以通过setAccessible(true)访问私有属性、方法,所以需要进行保证。一般是使用SecurityManager进行访问性的保证。可以自定义用户的SecurityManager,通过继承的方式。下面是一个例子。

    1. 方法一:继承securityManger
    2. 方法二:指定安全策略文件,然后通过System.setProperty(”java.security.policy“, 路径); System.setSecurityManager(new SecurityManager());进行保证

    方法一:

    import java.lang.reflect.ReflectPermission;
    
    public class SecurityManagerExample {
    
        public static void main(String[] args) {
            // 创建自定义的安全管理器
            SecurityManager securityManager = new CustomSecurityManager();
    
            // 设置自定义的安全管理器
            System.setSecurityManager(securityManager);
    
            // 尝试进行反射操作
            try {
                // 获取Class对象
                Class<?> clazz = MyClass.class;
    
                // 通过反射调用私有方法
                clazz.getDeclaredMethod("privateMethod").invoke(new MyClass());
            } catch (Exception e) {
                System.out.println("Security exception: " + e.getMessage());
            }
        }
    
        static class CustomSecurityManager extends SecurityManager {
            @Override
            public void checkPermission(java.security.Permission perm) {
                // 检查反射相关的权限
                if (perm instanceof ReflectPermission) {
                    String name = perm.getName();
                    if (name != null && name.startsWith("suppressAccessChecks")) {
                        throw new SecurityException("Reflective access is not allowed.");
                    }
                }
            }
        }
    
        static class MyClass {
            private void privateMethod() {
                System.out.println("This is a private method.");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    方法二:

    grant {
        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
    };
    
    • 1
    • 2
    • 3
    import java.lang.reflect.Method;
    
    public class SecurityPolicyExample {
    
        public static void main(String[] args) {
            // 设置安全策略文件路径
            System.setProperty("java.security.policy", "path/to/mysecurity.policy");
    
            // 启用安全管理器
            System.setSecurityManager(new SecurityManager());
    
            // 尝试进行反射操作
            try {
                // 获取Class对象
                Class<?> clazz = MyClass.class;
    
                // 通过反射调用私有方法
                Method privateMethod = clazz.getDeclaredMethod("privateMethod");
                privateMethod.setAccessible(true);
                privateMethod.invoke(new MyClass());
            } catch (Exception e) {
                System.out.println("Security exception: " + e.getMessage());
            }
        }
    
        static class MyClass {
            private void privateMethod() {
                System.out.println("This is a private method.");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    动态代理

    在运行期间创建某一个接口的实例。

    原理就是在运行期间动态创建class字节码并加载的过程

    使用proxy创建代理对象,将接口方法代理给InvokeHandler完成的。

    动态代理原理是反射。InvokeHandler的调用使用了反射的.class.getMethod方法。

  • 相关阅读:
    如何快速除掉项目中的console
    [极客大挑战 2019]LoveSQL
    博客应用与发展实验记录
    汇编语言程序设计·RB(AT&T汇编)_笔记_第6章:控制执行流程
    零基础重庆自考本科行政管理难吗?
    现在入行程序员,等于49年入国军
    企业自研业务系统的登录如何添加动态口令,实施MFA双因子认证?
    通往优秀软件架构师之路:掌握技术核心,修炼基础原理【文中送书,十本任选】
    【TES641】基于VU13P FPGA的4路FMC接口基带信号处理平台
    DAM Finance获得来自Arrington和Moonbeam生态增长基金的战略投资
  • 原文地址:https://blog.csdn.net/fuzekun/article/details/134264269