当前位置: 首页 > news >正文

java-反射 2

### 5. 反射在实际应用中的案例

#### 5.1 动态代理

动态代理是反射的重要应用之一,可以在运行时动态生成代理类,拦截方法调用。Java 提供了 `java.lang.reflect.Proxy` 类和 `java.lang.reflect.InvocationHandler` 接口来实现动态代理。

```java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface MyInterface {
    void myMethod();
}

class MyClass implements MyInterface {
    public void myMethod() {
        System.out.println("MyClass myMethod");
    }
}

class MyInvocationHandler implements InvocationHandler {
    private final Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method");
        Object result = method.invoke(target, args);
        System.out.println("After method");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass myObject = new MyClass();
        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                myObject.getClass().getClassLoader(),
                myObject.getClass().getInterfaces(),
                new MyInvocationHandler(myObject)
        );

        proxy.myMethod();
    }
}
```

#### 5.2 依赖注入

依赖注入(Dependency Injection, DI)是另一种常见的反射应用,许多框架(如 Spring)使用反射机制实现对象的依赖注入。

```java
import java.lang.reflect.Field;

class Service {
    public void serve() {
        System.out.println("Service is serving");
    }
}

class Client {
    private Service service;

    public void doSomething() {
        service.serve();
    }
}

public class Injector {
    public static void inject(Object target, String fieldName, Object dependency) throws Exception {
        Field field = target.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(target, dependency);
    }

    public static void main(String[] args) throws Exception {
        Client client = new Client();
        Service service = new Service();

        inject(client, "service", service);
        client.doSomething();
    }
}
```

### 6. 反射的性能和安全性问题

#### 6.1 性能问题

反射操作涉及大量的类型检查和安全检查,性能比直接调用要低。在性能敏感的场景中,应避免频繁使用反射。可以通过缓存反射对象(如 `Method`、`Field` 等)来减少性能开销。

#### 6.2 安全性问题

反射可以绕过访问控制,访问私有字段和方法,可能导致安全问题。在受限环境(如沙箱)中,应严格控制反射操作的权限。Java 安全管理器(Security Manager)可以用来限制反射操作。

### 7. 反射的限制和注意事项

#### 7.1 类型擦除

Java 泛型在运行时会被类型擦除,反射无法直接获取泛型参数类型。可以通过 `Type` 和 `ParameterizedType` 接口来处理泛型信息。

```java
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

class GenericClass<T> {
}

public class Main {
    public static void main(String[] args) {
        GenericClass<List<String>> genericObject = new GenericClass<>();
        Type type = genericObject.getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] typeArguments = parameterizedType.getActualTypeArguments();
            for (Type typeArgument : typeArguments) {
                System.out.println(typeArgument);
            }
        }
    }
}
```

#### 7.2 动态加载类

反射可以用于动态加载类,在运行时根据条件加载和使用不同的类。可以使用 `Class.forName` 方法动态

加载类。

```java
public class Main {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.example.MyClass");
            Object myObject = clazz.newInstance();
            Method method = clazz.getMethod("myMethod");
            method.invoke(myObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

### 8. 总结

Java 反射机制提供了一种在运行时动态操作对象的强大工具,通过反射可以动态地获取类的结构信息、创建对象、调用方法和访问字段。反射在动态代理、依赖注入、框架设计等方面具有广泛的应用。然而,反射操作具有一定的性能开销和安全性风险,在实际应用中应合理使用。通过理解和掌握反射机制,可以编写出更加灵活和可扩展的 Java 程序。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Segmentation fault (core dumped)
  • 3.结果映射ResultMap(关联association+collection)
  • 图像分割入门-SegNet理论与实践
  • Github绑定自己的域名
  • C语言 -- 操作符详解​
  • tableau气泡图与词云图绘制 - 8
  • 芯片基识 | 掰开揉碎讲 FIFO(同步FIFO和异步FIFO)
  • PID控制与模糊PID控制的比较
  • 预算有限?如何挑选经济适用的安全管理系统?
  • 识别色带后执行相应命令
  • Pandas在生物信息学中的应用详解
  • gazebo仿真环境中加入livox mid360
  • Oracle的主要特点是什么?应用场景有哪些?
  • 专业课笔记——(第九章:类的封装、继承、多态)
  • 使用 OpenCV 和 Python 进行车道检测和物体检测(YOLO)
  • Apache的80端口被占用以及访问时报错403
  • axios 和 cookie 的那些事
  • PHP 的 SAPI 是个什么东西
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • spring boot 整合mybatis 无法输出sql的问题
  • supervisor 永不挂掉的进程 安装以及使用
  • SwizzleMethod 黑魔法
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • vue-cli在webpack的配置文件探究
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​iOS安全加固方法及实现
  • #AngularJS#$sce.trustAsResourceUrl
  • #if和#ifdef区别
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (2)nginx 安装、启停
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (推荐)叮当——中文语音对话机器人
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .Net 8.0 新的变化
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .net的socket示例
  • .net专家(高海东的专栏)
  • .php文件都打不开,打不开php文件怎么办
  • @Autowired多个相同类型bean装配问题
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [c]统计数字
  • [C++]使用yolov10的onnx模型结合onnxruntime和bytetrack实现目标追踪
  • [hive]中的字段的数据类型有哪些
  • [IE编程] WebBrowser控件的多页面浏览(Tabbed Browsing)开发接口
  • [JAVA数组] 三个数的最大乘积