Java反射机制学习1

本文深入探讨了Java反射机制的原理与实践,包括如何在运行时获取类信息、访问类成员、调用方法等核心功能,并通过示例代码演示了反射在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java 反射机制可以让我们在编译期(Compile Time)之外的运行期(Runtime)检查类,接口,变量以及方法的信息。反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值。

下面是一个 Java 反射的简单例子:

import java.lang.reflect.Method;


public class MyObject {
    String name;
    String password;


    public MyObject(String name, String password) {
        super();
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    public static void main(String[] args) {
        Method[] methods = MyObject.class.getMethods();

        for(Method method : methods){
            System.out.println("method = " + method.getName());
        }
    }
}

在这个例子中通过调用 MyObject 类的 class 属性获取对应的 Class 类的对象,通过这个 Class 类的对象获取 MyObject 类中的方法集合。迭代这个方法的集合并且打印每个方法的名字。
输出结果:

method = main
method = getName
method = setName
method = getPassword
method = setPassword
method = wait
method = wait
method = wait
method = equals
method = toString
method = hashCode
method = getClass
method = notify
method = notifyAll

使用 Java 反射机制可以在运行时期检查 Java 类的信息,检查 Java 类的信息往往是你在使用 Java 反射机制的时候所做的第一件事情,通过获取类的信息你可以获取以下相关的内容:

Class 对象
类名
修饰符
包信息
父类
实现的接口
构造器
方法
变量
注解

Class 对象

在你想检查一个类的信息之前,你首先需要获取类的 Class 对象。Java 中的所有类型包括基本类型(int, long, float等等),即使是数组都有与之关联的 Class 类的对象。如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class 对象。

Class myObjectClass = MyObject.class;

如果你在编译期不知道类的名字,但是你可以在运行期获得到类名的字符串,那么你则可以这么做来获取 Class 对象:

String className = ... ;//在运行期获取的类名字符串
Class class = Class.forName(className);

在使用 Class.forName() 方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。例如 MyObject 类位于 com.jenkov.myapp 包,那么他的全名就是 com.jenkov.myapp.MyObject。 如果在调用Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出ClassNotFoundException。

类名

你可以从 Class 对象中获取两个版本的类名。
通过 getName() 方法返回类的全限定类名(包含包名):

Class aClass = ... //获取Class对象,具体方式可见Class对象小节
String className = aClass.getName();

如果你仅仅只是想获取类的名字(不包含包名),那么你可以使用 getSimpleName()方法:

Class aClass = ... //获取Class对象,具体方式可见Class对象小节
String simpleClassName = aClass.getSimpleName();

修饰符

可以通过 Class 对象来访问一个类的修饰符, 即public,private,static 等等的关键字,你可以使用如下方法来获取类的修饰符:

Class  aClass = ... //获取Class对象,具体方式可见Class对象小节
int modifiers = aClass.getModifiers();

修饰符都被包装成一个int类型的数字,这样每个修饰符都是一个位标识(flag bit),这个位标识可以设置和清除修饰符的类型。 可以使用 java.lang.reflect.Modifier 类中的方法来检查修饰符的类型:

Modifier.isAbstract(int modifiers);
Modifier.isFinal(int modifiers);
Modifier.isInterface(int modifiers);
Modifier.isNative(int modifiers);
Modifier.isPrivate(int modifiers);
Modifier.isProtected(int modifiers);
Modifier.isPublic(int modifiers);
Modifier.isStatic(int modifiers);
Modifier.isStrict(int modifiers);
Modifier.isSynchronized(int modifiers);
Modifier.isTransient(int modifiers);
Modifier.isVolatile(int modifiers);

包信息

可以使用 Class 对象通过如下的方式获取包信息:

Class  aClass = ... //获取Class对象,具体方式可见Class对象小节
Package package = aClass.getPackage();

通过 Package 对象你可以获取包的相关信息,比如包名,你也可以通过 Manifest 文件访问位于编译路径下 jar 包的指定信息,比如你可以在 Manifest 文件中指定包的版本编号。

父类

通过 Class 对象你可以访问类的父类,如下例:

Class superclass = aClass.getSuperclass();

可以看到 superclass 对象其实就是一个 Class 类的实例,所以你可以继续在这个对象上进行反射操作。
实现的接口

可以通过如下方式获取指定类所实现的接口集合:

Class  aClass = ... //获取Class对象,具体方式可见Class对象小节
Class[] interfaces = aClass.getInterfaces();

由于一个类可以实现多个接口,因此 getInterfaces(); 方法返回一个 Class 数组,在 Java 中接口同样有对应的 Class 对象。 注意:getInterfaces() 方法仅仅只返回当前类所实现的接口。当前类的父类如果实现了接口,这些接口是不会在返回的 Class 集合中的,尽管实际上当前类其实已经实现了父类接口。
构造器

你可以通过如下方式访问一个类的构造方法:

Constructor[] constructors = aClass.getConstructors();

更多有关 Constructor 的信息可以访问 Constructors。
方法

你可以通过如下方式访问一个类的所有方法:

Method[] method = aClass.getMethods();

变量

你可以通过如下方式访问一个类的成员变量:

Field[] method = aClass.getFields();

注解

你可以通过如下方式访问一个类的注解:

Annotation[] annotations = aClass.getAnnotations();

示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


public class MyObject {
    String name;
    String password;


    public MyObject(String name, String password) {
        super();
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    public static void main(String[] args) {
        Class myObject = MyObject.class;

        Method[] methods = myObject.getMethods();
        Field[] fields = myObject.getDeclaredFields();
        Constructor[] constructors = myObject.getDeclaredConstructors();

        System.out.println(myObject.getName());
        System.out.println(myObject.getPackage());
        System.out.println(myObject.getSuperclass());
        System.out.println(myObject.getSimpleName());
        System.out.println(myObject.getModifiers());
        for(Method method : methods){
            System.out.println("method = " + method.getName());
        }
        for(Field field : fields){
            System.out.println("field = " + field.getName());
        }
        for(Constructor constructor : constructors){
            System.out.println("constructor = " + constructor.getName());
        }
    }
}

输出结果:

MyObject
null
class java.lang.Object
MyObject
1
method = main
method = getName
method = setName
method = getPassword
method = setPassword
method = wait
method = wait
method = wait
method = equals
method = toString
method = hashCode
method = getClass
method = notify
method = notifyAll
field = name
field = password
constructor = MyObject
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值