java反射超详细讲解

yizhihongxing

Java反射超详细讲解

什么是Java反射

Java反射(Reflection)是指在程序运行时,可以对一个类进行解剖,获取到类的所有信息,包括类名、父类、接口、变量、方法等,并能够访问和操作对象的属性和方法。

正常情况下,我们在使用Java开发时,需要先编写好类,并通过该类生成对象,然后才能使用该对象的属性和方法。但是,当我们使用反射技术时,我们可以在不编写类和对象的情况下,直接通过类名操作对象的属性和方法,实现动态创建对象、调用方法等操作。

Java反射的优缺点

Java反射技术提供了很方便的动态操作对象的方式,但是也存在以下缺点:

  • 反射操作的可读性较差,代码难以维护;
  • 反射的性能较低,通常比直接调用方法要慢;
  • 反射需要运行时处理,可能导致运行时异常。

获取Class对象的方式

获取到Class对象是使用反射的前提,我们可以通过以下方式获取Class对象:

// 1. 使用类名获取Class对象
Class<?> cls = Class.forName("com.example.demo.User");

// 2. 使用类对象的getClass()方法获取Class对象
User user = new User();
Class<?> cls = user.getClass();

// 3. 使用.class语法获取Class对象
Class<?> cls = User.class;

获取类信息

获取到Class对象后,我们可以获取到类的一些信息,如类名、父类、接口、变量、方法等:

Class<?> cls = Class.forName("com.example.demo.User");

// 获取类名
String className = cls.getName();
System.out.println("类名:" + className);

// 获取父类名
Class<?> superClass = cls.getSuperclass();
System.out.println("父类名:" + superClass.getName());

// 获取实现的接口
Class<?>[] interfaces = cls.getInterfaces();
for (Class<?> c : interfaces) {
    System.out.println("实现的接口:" + c.getName());
}

// 获取所有的属性
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
    System.out.println("属性名:" + field.getName());
    System.out.println("属性类型:" + field.getType().getName());
    System.out.println("修饰符:" + Modifier.toString(field.getModifiers()));
}

// 获取所有的方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
    System.out.println("方法名:" + method.getName());
    System.out.println("方法返回值类型:" + method.getReturnType().getName());
    System.out.println("修饰符:" + Modifier.toString(method.getModifiers()));
    System.out.println("参数列表:");
    Class<?>[] parameterTypes = method.getParameterTypes();
    for (Class<?> parameterType : parameterTypes) {
        System.out.println(parameterType.getName());
    }
}

动态创建对象

使用反射技术,我们可以在程序运行时动态创建任意一个类的对象,示例如下:

Class<?> cls = Class.forName("com.example.demo.User");

// 动态创建User对象
User user = (User) cls.newInstance();

// 设置属性值
Field nameField = cls.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "张三");

Field ageField = cls.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(user, 18);

// 调用方法
Method sayHelloMethod = cls.getDeclaredMethod("sayHello");
sayHelloMethod.invoke(user);

动态代理

动态代理是一种非常重要的Java反射应用。使用动态代理可以在运行时动态地创建一个代理类,代理类可以充当目标对象的替身,并在代理类中调用目标对象的方法。常见的动态代理框架有JDK动态代理和cglib代理。

以下是JDK动态代理的示例:

// 定义目标类接口
interface UserDao {
    String save(String username);
}

// 定义目标类实现
class UserDaoImpl implements UserDao {
    @Override
    public String save(String username) {
        System.out.println("保存用户数据:" + username);
        return "保存成功";
    }
}

// 定义代理类
class UserDaoProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始保存用户数据");
        Object result = method.invoke(target, args);
        System.out.println("保存用户数据完成");
        return result;
    }
}

// 测试
UserDao userDao = new UserDaoImpl();
UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), new Class[]{UserDao.class}, new UserDaoProxy(userDao));
proxy.save("zhangsan");

总结

Java反射是一种非常强大的技术,可以实现很多动态操作对象的功能。但是,使用反射也需要注意性能和可读性等问题,适用时需要谨慎选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java反射超详细讲解 - Python技术站

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

相关文章

  • 优化spring boot应用后6s内启动内存减半

    优化 Spring Boot 应用可以显著降低应用启动进程所需的时间,同时减少内存占用,提高应用的性能。下面是优化 Spring Boot 应用的完整攻略: 1. 去除无用依赖 在应用启动过程中,Spring Boot 会扫描所有的依赖并生成一个应用的依赖关系树。因此,需要仅仅保留应用的所需依赖,去除无用依赖,减小应用的依赖树,加速应用的启动时间。 可以通过…

    Java 2023年6月3日
    00
  • JDBC数据库连接过程及驱动加载与设计模式详解

    下面是对于“JDBC数据库连接过程及驱动加载与设计模式详解”的完整攻略: JDBC数据库连接过程 JDBC是JavaEE标准中定义的用于操作各种关系型数据库的API。使用JDBC连接到数据库的过程如下: 加载数据库驱动:使用Class.forName(driver)加载对应数据库的驱动类,其中driver是JDBC提供的数据库驱动类名。例如,连接MySQL数…

    Java 2023年5月20日
    00
  • PerlScript编写ASP(转载)

    让我来详细讲解一下“PerlScript编写ASP(转载)”的完整攻略。 什么是PerlScript编写ASP? PerlScript编写ASP是一种使用PerlScript语言编写ASP的技术,与VBScript和JScript类似,PerlScript是一种基于Perl的脚本语言,它可以与ASP一起使用来生成动态网页。PerlScript编写ASP可以提…

    Java 2023年6月16日
    00
  • Mybatis面试题整理小结

    作为”Mybatis面试题整理小结”的作者,我将为你详细讲解如何攻略这份题目。整个攻略分为以下几个步骤: 步骤一:了解Mybatis的基础知识 首先,Mybatis是一款优秀的持久层框架,它基于Java语言,可以灵活地操作关系型数据库。在学习Mybatis之前,我们需要掌握一些基础知识,例如SQL语句的使用、Java对象映射等。如果你对这些知识还不太熟悉,建…

    Java 2023年5月20日
    00
  • 详解CentOS 7下安装Tomcat到服务

    下面是详解CentOS 7下安装Tomcat到服务的完整攻略,分为以下步骤: 步骤一:安装Java环境 在CentOS 7下安装Tomcat之前,需要先安装Java环境,这里我们使用OpenJDK: 更新软件包: sudo yum update 安装OpenJDK: sudo yum install java-1.8.0-openjdk-devel 验证Ja…

    Java 2023年5月19日
    00
  • 浅谈Java中Properties类的详细使用

    接下来我将详细讲解“浅谈Java中Properties类的详细使用”的完整攻略,内容如下: 1. Properties类介绍 Properties类是Java中的一个集合类,它继承了Hashtable类,并且具有以下特点: 它用于表示一组属性,属性的值可以是字符串 Properties对象通常用来存储配置文件中的键值对数据,也可以序列化到文件中或从文件中进行…

    Java 2023年6月15日
    00
  • java文件读写工具类分享

    Java文件读写工具类分享 在Java开发中,文件读写是一个十分普遍的操作。本文将会分享一个Java文件读写工具类,方便大家在开发中快速处理文件读写,提高开发效率。 工具类实现 Java文件读写需要使用到IO流,我们可以封装一个工具类,提供常见的文件读写操作。示例代码如下: import java.io.*; public class FileUtil { …

    Java 2023年5月20日
    00
  • 解决Mybatis中mapper.xml文件update,delete及insert返回值问题

    解决Mybatis中mapper.xml文件update,delete及insert返回值问题,需要在mapper.xml文件中使用select标签并指定resultType来解决。具体步骤如下: 在mapper.xml中编写对应的statement,如下: <!– update语句的示例 –> <update id="upd…

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