Java 反射

发布于:2025-08-19 ⋅ 阅读:(16) ⋅ 点赞:(0)
一. 反射概述

Java反射是Java语言的一种特性,它允许程序在运行时自我检查并对内部成员进行操作。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

优点:

  • 灵活性:反射允许程序在运行时动态地访问对象的信息和操作,这增加了程序的灵活性。
  • 通用性:可以编写更通用的代码,例如编写一个方法,它可以接受任何对象作为参数并调用其方法。
  • 框架和库开发:许多Java框架和库(如Spring框架)广泛使用反射来处理依赖注入、事件监听等。

缺点:

  • 安全性问题:反射可能导致安全漏洞,例如恶意代码可以利用它来访问或修改不应被访问的系统内部信息
  • 性能开销:反射操作通常比直接代码调用要慢,因为它涉及到类型信息的动态解析。在性能敏感的应用中,过度使用反射可能会导致性能问题。
  • 可读性和维护性:使用反射编写的代码通常比直接代码更难理解和维护,因为它增加了代码的复杂性和间接性。
二. 使用反射

在Java编程语言中,Class类是一个特殊的类,它用于表示JVM运行时的类或接口的信息。你可以把它看作是一个普通的类,但它描述的是所有的类的公共特性。

每个类在Java中都对应着一个Class对象,这个对象保存了该类的结构信息,如类名、字段、方法等。换句话说,Class类是一个反射工具,能提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。

1. 获取Class对象
  1. Class.forName(“全类名”)
  2. 类名.class
  3. 对象名.getClass()

先新建一个Student测试类

package org.example.reflect;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;


@Getter
@Setter
@ToString
public class Student {
    private String name;
    private int age;


    private Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(int age) {
        this.age = age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private void eat(String food) {
        System.out.println("I am eating " + food);
    }
}

下面演示如何获取Class对象

package org.example.reflect;

public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> c1 = Class.forName("org.example.reflect.Student");

        Class<Student> c2 = Student.class;
        
        Student student = new Student("zhangsan");
        Class<? extends Student> c3 = student.getClass();

        System.out.println(c1 == c2);
        System.out.println(c2 == c3);
    }
}

运行结果:

true
true
2. 获取构造方法
public Constructor<?>[] getConstructors()    //获取公开的构造方法
public Constructor<?>[] getConstructors()    //获取所有的公开的构造方法
public Constructor<?>[] getDeclaredConstructors()   //获取所有的构造方法,包括私有
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)   //获取指定包括私有,不包括继承的Constructor对象

下面演示如何获取Student类的构造方法

package org.example.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;

public class ReflectDemo2 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> clazz = Class.forName("org.example.reflect.Student");

        // 获取public 构造方法
        System.out.println("===== public构造方法 =====");
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor constructor: constructors) {
            System.out.println(constructor);
        }

        System.out.println("===== 所有构造方法 =====");
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor constructor: declaredConstructors) {
            System.out.println(constructor);
        }


        // 不传参数表示获取空参构造函数
        System.out.println("===== 获取单个构造方法 =====");
        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor);

        // 获取构造函数参数
        System.out.println("===== 获取构造函数参数 =====");
        Parameter[] parameters = declaredConstructor.getParameters();
        for (Parameter parameter: parameters) {
            System.out.println(parameter);
        }

        System.out.println("===== 实例化对象 =====");
        declaredConstructor.setAccessible(true);
        Object instance = declaredConstructor.newInstance("chenli", 30);
        System.out.println(instance);
    }
}

运行结果:

===== public构造方法 =====
public org.example.reflect.Student(java.lang.String,int)
public org.example.reflect.Student(int)
public org.example.reflect.Student(java.lang.String)
===== 所有构造方法 =====
public org.example.reflect.Student(java.lang.String,int)
public org.example.reflect.Student(int)
public org.example.reflect.Student(java.lang.String)
private org.example.reflect.Student()
===== 获取单个构造方法 =====
public org.example.reflect.Student(java.lang.String,int)
===== 获取构造函数参数 =====
java.lang.String arg0
int arg1
===== 实例化对象 =====
Student(name=chenli, age=30)
3. 获取成员变量
public Field[] getFields()  //获取所有公开的成员变量,包括继承变量
public Field[] getDeclaredFields()  //获取本类定义的成员变量,包括私有,但不包括继承的变量
public Field getField(String name)   //获取指定公共属性的Field对象
public Field getDeclaredField(String name)  //获取指定包括私有,不包括继承的Field对象

下面演示如何获取Student类的成员变量

package org.example.reflect;

import java.lang.reflect.Field;

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("org.example.reflect.Student");

        System.out.println("===== 获取所有属性 =====");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field: fields) {
            System.out.println(field);
        }

        System.out.println("===== 获取属性信息 =====");
        Field nameField = clazz.getDeclaredField("name");
        String name = nameField.getName();
        Class<?> type = nameField.getType();
        System.out.println("name: " + name + ", type: " + type);

        // 修改field的值
        System.out.println("===== 修改对象的属性 =====");
        Student s = new Student("zhangsan", 20);
        System.out.println(s);
        nameField.setAccessible(true);
        nameField.set(s, "lisi");
        System.out.println(s);
    }
}

运行结果:

===== 获取所有属性 =====
private java.lang.String org.example.reflect.Student.name
private int org.example.reflect.Student.age
===== 获取属性信息 =====
name: name, type: class java.lang.String
===== 修改对象的属性 =====
Student(name=zhangsan, age=20)
Student(name=lisi, age=20)
4. 获取成员方法
public Method[] getMethods()  //获取所有可见的方法,包括继承的方法
public Method getMethod(String name, Class<?>... parameterTypes)  //获取指定方法的Method对象
public Method[] getDeclaredMethods()   //获取本类定义的的方法,包括私有,不包括继承的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)  //获取指定包括私有,不包括继承的Method对象

下面演示如何获取Student类的成员方法

package org.example.reflect;

import java.lang.reflect.Method;

public class ReflectDemo4 {

    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("org.example.reflect.Student");

        System.out.println("===== 获取所有方法 =====");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method: declaredMethods) {
            System.out.println(method);
        }

        System.out.println("===== 获取某个方法 =====");
        Method method = clazz.getDeclaredMethod("eat", String.class);
        String name = method.getName();
        Class<?> returnType = method.getReturnType();
        Class<?>[] parameterTypes = method.getParameterTypes();
        System.out.println("name: " + name + ", returntype: " + returnType
        + "parameterTypes: " + parameterTypes);

        System.out.println("===== 调用方法 =====");
        Student s = new Student("kkk", 30);
        method.setAccessible(true);
        method.invoke(s, "apple");
    }
}

运行结果:

===== 获取所有方法 =====
public java.lang.String org.example.reflect.Student.toString()
public java.lang.String org.example.reflect.Student.getName()
public void org.example.reflect.Student.setName(java.lang.String)
private void org.example.reflect.Student.eat(java.lang.String)
public int org.example.reflect.Student.getAge()
public void org.example.reflect.Student.setAge(int)
===== 获取某个方法 =====
name: eat, returntype: voidparameterTypes: [Ljava.lang.Class;@5cad8086
===== 调用方法 =====
I am eating apple

网站公告

今日签到

点亮在社区的每一天
去签到