Java 反射(Reflect)详解

yizhihongxing

Java 反射(Reflect)详解

什么是反射?

反射是指Java程序可以检查自身的能力,并且在运行时获取和操作自身的类、接口、方法和属性等信息。Java反射提供了一种机制使得一个程序在运行期间可以获取自身的信息并且可以操作该类的内部属性、方法和构造方法。

反射的作用

反射主要有如下应用场景:

  • 动态创建对象或获取已有对象的信息;
  • 调用对象的方法;
  • 访问和修改类的成员变量等。

反射可以做很多的事情,例如动态创建对象、动态获取类的方法或属性信息、动态调用方法,还可以实现IOC容器、代理对象等功能。

反射相关概念

在了解反射之前,首先需要了解以下三个概念:

  • Class类:用于表示类或接口的实体,并提供了获取类或接口的变量、属性、方法和构造方法等信息的功能。
  • Field类:用于描述类或接口中的属性信息。
  • Method类:用于描述类或接口中的方法信息。

反射API的使用

获取Class类实例对象

Class<?> clazz = Class.forName("java.lang.String");

获取类的属性

Class<?> clazz = Class.forName("com.example.User");
Field[] fields = clazz.getDeclaredFields(); // 获取类中所有属性
for (Field field : fields) {
    System.out.println(field.getName()); // 输出属性名
}

获取类的方法

Class<?> clazz = Class.forName("com.example.User");
Method[] methods = clazz.getMethods(); // 获取类中所有方法
for (Method method : methods) {
    System.out.println(method.getName()); // 输出方法名
}

调用方法

Class<?> clazz = Class.forName("com.example.User");
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setName", String.class);
method.invoke(obj, "jack"); // 调用 setName 方法设置属性值

示例说明一:动态代理

动态代理是指在程序运行时生成代理类、代理对象,代替原有的类或对象,实现同样的接口或方法,并对委托的真实对象进行控制。在Java中,动态代理是基于反射实现的,即动态代理生成的类是基于原来类的实现,因此我们需要通过反射得到原来类的接口或方法信息。

// 定义接口
public interface UserService {
    String sayHello(String msg);
}

// 实现接口
public class UserServiceImpl implements UserService {
    @Override
    public String sayHello(String msg) {
        return "Hello " + msg + "!";
    }
}

// 生成代理类
public class UserServiceProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

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

// 调用代理类的方法
public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserServiceProxy proxy = new UserServiceProxy();
        UserService proxyService = (UserService) proxy.bind(userService);
        proxyService.sayHello("Jack");
    }
}

示例说明二:使用注解实现自定义ORM框架

ORM (Object Relational Mapping)框架是指通过反射实现Java对象与数据库表之间的映射。在Java程序中,可以使用注解定义与数据库表对应的实体类对象,并使用反射读取注解信息。同时,也可以使用Class类提供的一些方法获取实体类对象中的成员变量和成员方法,并使用数据库操作API实现数据库的CRUD操作。

// 定义注解
@Target(ElementType.FIELD) // 表示注解用在类的属性上
@Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时保留
public @interface Column {
    String name() default ""; // 数据库字段名称
}

// 定义实体类
public class User {
    @Column(name = "id")
    private int id;
    @Column(name = "name")
    private String name;
    @Column(name = "age")
    private int age;
}

// 读取注解信息
public static String getColumnValue(Object obj, String columnName) throws Exception {
    Class<?> clazz = obj.getClass();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        if (field.isAnnotationPresent(Column.class)) {
            Column column = field.getAnnotation(Column.class);
            if (column.name().equals(columnName)) {
                field.setAccessible(true);
                return String.valueOf(field.get(obj)); // 返回指定属性名的属性值
            }
        }
    }
    return null;
}

// 使用数据库操作API实现数据库的CRUD操作
public static void save(Object obj) throws Exception {
    Class<?> clazz = obj.getClass();
    StringBuilder sb = new StringBuilder();
    StringBuilder sbValue = new StringBuilder();
    sb.append("insert into ").append(clazz.getSimpleName()).append("(");
    sbValue.append(" values(");
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        if (field.isAnnotationPresent(Column.class)) {
            Column column = field.getAnnotation(Column.class);
            sb.append(column.name()).append(",");
            sbValue.append("'").append(getColumnValue(obj, column.name())).append("',");
        }
    }
    sb.deleteCharAt(sb.length() - 1).append(")");
    sbValue.deleteCharAt(sbValue.length() - 1).append(")");
    String sql = sb.toString() + sbValue.toString();
    // 执行数据库插入操作
    System.out.println(sql);
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 反射(Reflect)详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 使用springboot+druid双数据源动态配置操作

    下面是“使用SpringBoot+Druid双数据源动态配置操作”的完整攻略及两条示例。 一、概述 在实际的项目开发中,经常会遇到同时操作多个不同的数据库的情况,比如读写分离、多租户等。使用SpringBoot+Druid双数据源动态配置操作,可以有效地解决这些问题。 二、配置SpringBoot+Druid 1. 引入相关依赖 在 pom.xml 文件中加…

    Java 2023年5月20日
    00
  • Java AOP知识详细介绍

    Java AOP知识详细介绍 什么是AOP AOP(Aspect-Oriented Programming)即面向切面编程,它能够将分散在应用程序各个部分的不同行为进行归纳和集中处理,使得横向依赖关系得到了有效管理,易于程序的开发和维护。 AOP术语 Aspect(切面):横向关注点,其中包括一组横跨多个对象的行为。 Join point(连接点):在程序执…

    Java 2023年5月26日
    00
  • 解决Spring Security中AuthenticationEntryPoint不生效相关问题

    当我们在使用Spring Security的时候,有时候可能会遇到AuthenticationEntryPoint不会被自动调用的问题。这个问题的原因可能是我们自定义的AuthenticationEntryPoint没有被正确配置或者是我们没有理解AuthenticationEntryPoint的工作原理。接下来我将为大家提供一个完整攻略,以解决Spring…

    Java 2023年6月3日
    00
  • java去除数组重复元素的四种方法

    关于“java去除数组重复元素的四种方法”的完整攻略,我给您详细讲解。 一、方法一:使用Set去重 使用Set去重是一种简单而高效的方法,它利用Set集合的特点,将重复元素去除,最终得到一个无序不重复的数组。具体步骤如下: 将数组转换为List集合。 创建一个新的HashSet集合。 将List中的元素依次加入HashSet中。 将HashSet转换为数组。…

    Java 2023年5月26日
    00
  • Java实现文件上传的方法总结

    Java实现文件上传的方法总结 本文将介绍 Java 实现文件上传的相关知识,包括上传步骤、上传方式和实现流程等。 上传步骤 Java 实现文件上传包含以下步骤: 准备上传文件。将需要上传的文件准备好。 发送请求。将上传请求发送至上传服务器。 接受请求。上传服务器接收上传请求。 上传文件。将文件上传至上传服务器。 发送响应。上传服务器发送文件上传成功或失败的…

    Java 2023年5月20日
    00
  • Java基本语法笔记(菜鸟必看篇)

    Java基本语法笔记(菜鸟必看篇) 数据类型 Java 中的基本数据类型包括整型、浮点型、布尔型、字符型和字符串型,它们分别为 int、float、double、boolean、char 和 String 类型。 整型 整型又分为四种类型:byte、short、int、long,不同的类型占用的内存大小不同,范围也不同。 byte:占1个字节,范围是 -12…

    Java 2023年5月23日
    00
  • 详细分析JAVA加解密算法

    详细分析JAVA加解密算法 在JAVA中,常用的加解密算法包括对称加密算法、非对称加密算法和HASH算法。在这里,我们将详细分析这些加解密算法的实现过程以及相关代码示例。 对称加密算法 对称加密算法使用同一个密钥进行加密和解密。其加密过程简单、高效,但密钥的共享是该算法的重要瓶颈。 在JAVA中,常用的对称加密算法包括DES、3DES、AES和Blowfis…

    Java 2023年5月19日
    00
  • Java字节码的增强技术

    Java字节码增强技术是指通过修改字节码来增强Java程序的功能,这种技术对于某些需要在运行时动态修改代码的场景非常有用,比如AOP、代码注入等。本文将介绍如何使用Java字节码增强技术来实现某些常见的场景。 1. 使用字节码增强技术来实现AOP AOP是一种面向切面编程的思想,它可以在不修改原有代码的情况下为程序添加切面功能。在Java中,AOP通常是通过…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部