Java 基础知识之 Java 反射

简介: 什么是Java反射?Java 反射机制是 Java 自诞生以来就具备的能力,用于在 Java 程序运行过程中动态的获取类的信息,调用类中的方法。

什么是Java反射?

Java 反射机制是 Java 自诞生以来就具备的能力,用于在 Java 程序运行过程中动态的获取类的信息,调用类中的方法。


Java 反射的使用场景

获取类的信息:如 Spring 中通过读取类的注解信息注册 Bean 对象。

调用类的方法:Spring 可以读取 XML 的配置信息,选择恰当的构造器,通过反射实例化 Bean 对象。

Java 反射机制提供了哪些 API ?

Java 虚拟机将字节码加载到内存中,并且抽象出了一些 Java 类。当程序运行时,可以通过这些类获取字节码中类的元信息。


Java反射的包名为java.lang.reflect,主要的 UML 类图如下。

image.png


反射相关的类主要如下:


Class:表示Java类。

Field:表示Java类中的成员变量。

Method:表示Java类中的成员方法。

Constructor:表示Java类的构造方法。

其他类如下:


Array:表示数组。

AnnotatedElement:JDK 1.5 新增,泛型相关,表示可以被注解标注的元素,如类、成员变量、

方法等。

Member:表示 Java 类中的成员,如成员变量,成员方法,构造方法。

AccessibleObject:JDK 1.2 新增,Field、Method、Constructor的父接口,提供对反射对象抑制默认的 Java 访问控制检查的能力。

GenericDeclaration:JDK 1.5 新增,泛型相关,表示可以定义类型变量的元素。

Type:JDK 1.5 新增,表示 Java 中的某一种类型。

Parameter:JDK 1.8 新增,表示成员方法或构造方法中的某一个参数。

AnnotatedType:JDK 1.8 新增,表示可以被注解标注的类型。

Executable:JDK 8 新增,Method 和 Constructor 的父接口。

TypeVariable:JDK 1.5 新增,泛型相关,类型变量,如List 中的 T。

GenericArrayType:JDK 1.5 新增,泛型相关,泛型数组类型,如 T[] 。

ParameterizedType:JDK 1.5 新增,泛型相关,参数化类型,如 Class 。

WildcardType:JDK 1.5 新增,泛型相关,通配符类型,如 Class 中的 ? extend Number。


Class 类

Class 类表示 Java 中的某一个类,不包含类的泛型信息。


获取方式主要有三种,如下:


java.lang.Class#forName(java.lang.String):如 Class cls = Class.forName("com.mysql.cj.jdbc.Driver")。

java.lang.Object#getClass:如 Class cls = "hello,java".getClass()。

Type.class:如 Class cls = String.class。

Class 类中常用的方法如下:


类定义相关方法

image.png


类成员相关方法

类成员包括内部类、构造方法(Constructor)、成员变量(Field)和成员方法(Method)。

下表中的 XXX 可以表示 Field、Constructor 或者 Method。


image.png

其他方法

image.png


Field 类

Field 通过 Class 的 getDeclaredField(…)、getDeclaredFields()、getField(…) 或者 getFields() 方法获取,主要提供了设置和获取成员变量值的方法。

具体如下,其中XXX可以表示 Boolean、Byte、Char、Short、Int、Long、Float、Double。


image.png


Constructor 类

Constructor 表示构造方法,主要提供了实例化 Java 对象的方法,具体如下。


image.png

Method 类

Method 表示 Java 中的方法,经常用来调用方法,主要的方法如下。


image.png

反射使用示例

示例1,打印给定类的结构

代码如下:

package com.zzuhkp;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
 * @author zzuhkp
 * @date 2020-08-05 9:48
 * @since 1.0
 */
public class ReflectTest {
    @NotBlank(message = "名称不能为空")
    private String name;
    public static void main(String[] args) {
        printClass(ReflectTest.class);
    }
    @Deprecated
    public static void printClass(@NotNull Class<?> cls) {
        StringBuilder sb = new StringBuilder();
        // 获取包信息
        Package aPackage = cls.getPackage();
        if (aPackage != null) {
            sb.append("package ").append(aPackage.getName()).append(";\n\n");
        }
        // 获取类修饰符信息
        String modifier = Modifier.toString(cls.getModifiers());
        if (modifier.length() > 0) {
            sb.append(modifier).append(" ");
        }
        // 获取类名
        sb.append("class ").append(cls.getSimpleName()).append(" ");
        // 获取父类
        Type superclass = cls.getGenericSuperclass();
        if (superclass != Object.class) {
            sb.append("extend ").append(superclass.getTypeName()).append(" ");
        }
        // 获取接口
        Type[] interfaces = cls.getGenericInterfaces();
        if (interfaces.length > 0) {
            String interfaceStr = Arrays.stream(interfaces).map(Type::getTypeName).collect(Collectors.joining(","));
            sb.append("implements ").append(interfaceStr).append(" ");
        }
        sb.append("{\n\n");
        // 获取成员变量
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            //获取成员变量的注解
            for (Annotation annotation : field.getAnnotations()) {
                sb.append("    ").append(annotation).append("\n");
            }
            // 获取成员变量修饰符
            String fieldModifier = Modifier.toString(field.getModifiers());
            // 获取成员变量类型名称
            String fieldTypeName = field.getGenericType().getTypeName();
            // 获取成员变量名称
            String fieldName = field.getName();
            sb.append("    ").append(fieldModifier).append(" ").append(fieldTypeName)
                .append(" ").append(fieldName).append(";\n");
        }
        sb.append("\n");
        Constructor<?>[] constructors = cls.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            for (Annotation annotation : constructor.getAnnotations()) {
                sb.append("    ").append(annotation).append("\n");
            }
            sb.append("    ");
            // 获取构造方法修饰符
            int constructorModifiers = constructor.getModifiers();
            String methodModifier = Modifier.toString(constructorModifiers);
            if (methodModifier.length() > 0) {
                sb.append(methodModifier).append(" ");
            }
            // 获取构造方法名称
            String constructorName = constructor.getName();
            sb.append(constructorName).append("(");
            // 获取方法参数
            String parameters = Arrays.stream(constructor.getParameters())
                .map(parameter -> {
                    // 获取方法参数注解
                    String str = Arrays.stream(parameter.getAnnotations()).map(Annotation::toString)
                        .collect(Collectors.joining(" "));
                    if (str.length() > 0) {
                        str = str + " ";
                    }
                    // 获取方法参数类型及名称
                    str = str + parameter.getParameterizedType().getTypeName() + " " + parameter.getName();
                    return str;
                })
                .collect(Collectors.joining(","));
            sb.append(parameters);
            sb.append(")");
            if (!Modifier.isNative(constructorModifiers)) {
                sb.append("{\n").append("        ..\n").append("    }");
            } else {
                sb.append(";");
            }
            sb.append("\n");
        }
        // 获取成员方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            for (Annotation annotation : method.getAnnotations()) {
                sb.append("    ").append(annotation).append("\n");
            }
            sb.append("    ");
            // 获取成员方法修饰符
            int methodModifiers = method.getModifiers();
            String methodModifier = Modifier.toString(methodModifiers);
            if (methodModifier.length() > 0) {
                sb.append(methodModifier).append(" ");
            }
            // 获取成员方法返回值类型
            String returnType = method.getGenericReturnType().getTypeName();
            sb.append(returnType).append(" ");
            // 获取成员方法名称
            String methodName = method.getName();
            sb.append(methodName).append("(");
            // 获取方法参数
            String parameters = Arrays.stream(method.getParameters())
                .map(parameter -> {
                    // 获取方法参数注解
                    String str = Arrays.stream(parameter.getAnnotations()).map(Annotation::toString)
                        .collect(Collectors.joining(" "));
                    if (str.length() > 0) {
                        str = str + " ";
                    }
                    // 获取方法参数类型及名称
                    str = str + parameter.getParameterizedType().getTypeName() + " " + parameter.getName();
                    return str;
                })
                .collect(Collectors.joining(","));
            sb.append(parameters);
            sb.append(")");
            if (!Modifier.isNative(methodModifiers)) {
                sb.append("{\n").append("        ..\n").append("    }");
            } else {
                sb.append(";");
            }
            sb.append("\n");
        }
        sb.append("}");
        System.out.println(sb);
    }
}


执行结果如下:


package com.zzuhkp;
public class ReflectTest {
    @javax.validation.constraints.NotBlank(message=名称不能为空, groups=[], payload=[])
    private java.lang.String name;
    public com.zzuhkp.ReflectTest(){
        ..
    }
    public static void main(java.lang.String[] args){
        ..
    }
    private static java.lang.String lambda$printClass$1(java.lang.reflect.Parameter parameter){
        ..
    }
    @java.lang.Deprecated()
    public static void printClass(@javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, groups=[], payload=[]) java.lang.Class<?> cls){
        ..
    }
    private static java.lang.String lambda$printClass$0(java.lang.reflect.Parameter parameter){
        ..
    }
}


示例2,通过反射调用方法


代码如下:


public class ReflectTest {
   static class Test {
        private void sayHello() {
            System.out.println("你好,Java");
        }
    }
    public static void main(String[] args)
        throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Test test = new Test();
        Method method = Test.class.getDeclaredMethod("sayHello");
        method.setAccessible(true);
        method.invoke(test);
    }
}


执行结果如下:


你好,Java


可以看到,私有的方法也可以通过反射进行调用。

目录
相关文章
|
30天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
52 1
|
2月前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
3月前
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
|
3月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
3月前
|
Java
Java的反射
Java的反射。
49 2
|
4月前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
68 0
[Java]反射
|
4月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
36 0
|
4月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
51 2
|
4月前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
49 1
|
4月前
|
Oracle Java 关系型数据库

热门文章

最新文章