• 【重铸Java根基】理解Java反射机制


    最近带应届新员工,教然后知不足,发现自己把很多基础知识已经还给了大学老师,因此开贴,温故而知新!

    从最基础的Java知识开始由浅入深,在某个知识点中遇到有疑惑的点会额外多写几句或者单独开帖子展开。

    本篇内容围绕Java反射机制,后续分享Java代理机制

    先搞清楚什么是反射?

    通过反射可以获取一个类的名称、属性和方法,可以调用方法、修改属性

    反射为我们提供了在运行时分析类的属性和调用类的方法的能力

    反射在哪里运用?

    平时在编写业务代码时很少用到反射,但是反射被大量运用于我们常用的开发框架中,像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。

    这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。

    比如下面是通过 JDK 实现动态代理的示例代码,其中就使用了反射类 Method 来调用指定的方法。

    1. public class DebugInvocationHandler implements InvocationHandler {
    2. /**
    3. * 代理类中的真实对象
    4. */
    5. private final Object target;
    6. public DebugInvocationHandler(Object target) {
    7. this.target = target;
    8. }
    9. public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
    10. System.out.println("before method " + method.getName());
    11. Object result = method.invoke(target, args);
    12. System.out.println("after method " + method.getName());
    13. return result;
    14. }
    15. }

    Java提供的反射相关接口

    获取某个类的几种方式:

    1. 知道具体类的情况下可以使用:

    Class alunbarClass = TargetObject.class;
    

    但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化

    2. 通过 Class.forName()传入类的全路径获取:

    Class alunbarClass1 = Class.forName("cn.jlwyz.TargetObject");
    

    3. 通过对象实例instance.getClass()获取:

    1. TargetObject o = new TargetObject();
    2. Class alunbarClass2 = o.getClass();

    4. 通过类加载器xxxClassLoader.loadClass()传入类路径获取:

    ClassLoader.getSystemClassLoader().loadClass("cn.jlwyz.TargetObject");
    

    通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

    反射的一些基本操作

    创建一个我们要使用反射操作的类 TargetObject

    1. public class TargetObject {
    2. private String value;
    3. public TargetObject() {
    4. value = "jlwyz";
    5. }
    6. public void publicMethod(String s) {
    7. System.out.println("I love " + s);
    8. }
    9. private void privateMethod() {
    10. System.out.println("value is " + value);
    11. }
    12. }

    使用反射操作这个类的方法以及参数

    1. public class Main {
    2. public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
    3. /**
    4. * 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
    5. */
    6. Class targetClass = Class.forName("cn.jlwyz.TargetObject");
    7. TargetObject targetObject = (TargetObject) targetClass.newInstance();
    8. /**
    9. * 获取 TargetObject 类中定义的所有方法
    10. */
    11. Method[] methods = targetClass.getDeclaredMethods();
    12. for (Method method : methods) {
    13. System.out.println(method.getName());
    14. }
    15. /**
    16. * 获取指定方法并调用
    17. */
    18. Method publicMethod = targetClass.getDeclaredMethod("publicMethod",
    19. String.class);
    20. publicMethod.invoke(targetObject, "jlwyz");
    21. /**
    22. * 获取指定参数并对参数进行修改
    23. */
    24. Field field = targetClass.getDeclaredField("value");
    25. //为了对类中的参数进行修改我们取消安全检查
    26. field.setAccessible(true);
    27. field.set(targetObject, "jlwyz");
    28. /**
    29. * 调用 private 方法
    30. */
    31. Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
    32. //为了调用private方法我们取消安全检查
    33. privateMethod.setAccessible(true);
    34. privateMethod.invoke(targetObject);
    35. }
    36. }
  • 相关阅读:
    es部署保姆教程
    html笔记__表格标签
    java 日期格式转换
    【区块链 + 智慧政务】一体化政务数据底座平台 | FISCO BCOS应用案例
    WEB前端常规技术面试题之HTML+CSS基础
    将web前端项目部署到github,在hbuilderx中部署github中的项目、对Github加速
    客户:我们系统太多,能不能实现多账号互通?
    实验(六):定时器实验
    鼠标右键展示“用Hbuilder“打开方法
    C语言内存函数
  • 原文地址:https://blog.csdn.net/playadota/article/details/126159314