Java 反射(Reflect)详解

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 如何使用Dataway配置数据查询接口

    下面是 SpringBoot 如何使用 Dataway 配置数据查询接口的攻略。 什么是 Dataway? Dataway 是由阿里巴巴集团开源的一款数据查询接口配置工具,它可以通过简单的配置生成符合 RESTful 风格的 HTTP 接口,从而快速完成前后端分离架构下的数据查询接口的开发。 SpringBoot 如何使用 Dataway 配置数据查询接口?…

    Java 2023年5月20日
    00
  • 从云数据迁移服务看MySQL大表抽取模式的原理解析

    从云数据迁移服务看MySQL大表抽取模式的原理解析 前言 MySQL是目前互联网应用中广泛使用的关系型数据库之一,但是在处理大量数据时,由于MySQL存储引擎特性和限制导致单表数据量的限制相对较小。为了解决这个问题,可以采用大表抽取的方式,将数据按照一定的规则划分成小批量进行处理。本文从云数据迁移服务角度,结合大表抽取进行原理解析。 什么是云数据迁移服务? …

    Java 2023年6月16日
    00
  • Spring实战之Bean的作用域request用法分析

    Spring实战之Bean的作用域request用法分析 什么是Bean作用域 在Spring中,Bean作用域指的是一个Bean实例的创建和存在方式。Spring框架中有多种Bean作用域,包括“singleton”、“prototype”、“request”等。 singleton:Bean在整个应用程序中只有一个实例,即在容器启动时,Spring IO…

    Java 2023年5月19日
    00
  • 如何保证Java线程安全性?

    为了保障Java程序的正确运行,我们需要确信Java线程的安全性。在Java语言中,可以使用以下几种方式来保证线程安全性: 使用同步块(Synchronized Block)或者同步方法(Synchronized Method)来保护共享变量。将多个线程对共享变量的访问限制为同一时间内只能有一个线程进行操作,从而保障数据的正确性和线程安全性。示例代码如下: …

    Java 2023年5月11日
    00
  • Spring Security如何在Servlet中执行

    Spring Security 是 Spring 框架中的一个安全框架,可以用于保护 Web 应用程序的安全,包括身份验证、授权、防止攻击等功能。在 Servlet 中使用 Spring Security 可以有效地保护应用程序的安全,下面是详细的使用攻略。 1. 添加 Spring Security 依赖 首先,需要在项目中添加 Spring Securi…

    Java 2023年5月20日
    00
  • 简单了解Spring Web相关模块运行原理

    简单了解Spring Web相关模块运行原理 Spring Web是一个基于Spring框架的Web开发框架,它提供了构建Web应用程序和RESTful Web服务所需的所有功能。在了解Spring Web相关模块的运行原理之前,需要首先了解Spring MVC的基本原理。 Spring MVC基本原理 Spring MVC是一种基于模型-视图-控制器(MV…

    Java 2023年5月31日
    00
  • springboot集成开发实现商场秒杀功能

    下面是详细讲解”springboot集成开发实现商场秒杀功能”的完整攻略。 1. 环境搭建 在开始之前,需要先确保你已经安装了以下环境: JDK1.8及以上 Maven3.3及以上 IDE(比如IntelliJ IDEA、Eclipse) 2. 导入依赖 在pom.xml文件中添加以下依赖: <dependency> <groupId&gt…

    Java 2023年5月19日
    00
  • Netty与Spring Boot的整合实现

    现在我将详细讲解“Netty与SpringBoot的整合实现”的完整攻略,以及其中涉及的两个示例。 概述 Netty和SpringBoot是目前广泛应用于Java开发的两个框架。Netty是一款基于NIO的客户端-服务端网络应用框架,可以快速开发各种网络应用,比如各种协议的服务器和客户端。而SpringBoot则是一种基于Spring框架的快速应用开发框架,…

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