1. 概述

Class 类在 Java 反射中扮演着重要角色,它是所有反射操作的入口点。

在这个快速教程中,我们将探讨如何从一个字符串形式的类名获取 Class 对象。

2. 问题介绍

首先,我们创建一个简单的类作为示例:

package com.baeldung.getclassfromstr;

public class MyNiceClass {
    public String greeting(){
        return "Hi there, I wish you all the best!";
    }
}

如代码所示,**MyNiceClass 类被创建在包 com.baeldung.getclassfromstr 中**。此外,该类只有一个方法 greeting(),返回一个 String 类型。

我们的目标是根据类名获取 MyNiceClassClass 对象,并且想从 Class 对象创建一个 MyNiceClass 的实例,以验证所获取的 Class 对象是否是我们想要的。

为了简化,我们将使用单元测试断言来验证我们的解决方案是否按预期工作。

接下来,让我们实际操作一下。

3. 使用 forName() 方法获取 Class 对象

Class 类提供了 forName(String) 方法,从一个字符串形式的类名获取 Class 对象。现在,让我们看看如何调用此方法获取 MyNiceClassClass 对象:

Class cls = Class.forName("com.baeldung.getclassfromstr.MyNiceClass");
assertNotNull(cls);

接着,我们可以使用 Class 对象 cls 创建一个 MyNiceClass 实例。如果我们的 Java 版本低于 9,可以使用 cls.newInstance() 方法获取实例。然而,自 Java 9 开始,这个方法已被弃用。对于新版本的 Java,我们可以使用 cls.getDeclaredConstructor().newInstance()Class 对象获取新实例:

MyNiceClass myNiceObject = (MyNiceClass) cls.getDeclaredConstructor().newInstance();
assertNotNull(myNiceObject);
assertEquals("Hi there, I wish you all the best!", myNiceObject.greeting());

当我们运行测试时,它会通过。因此,我们已经从类名获得了期望的 Class 对象。

值得一提的是,为了获取 Class 对象,我们必须将完整的类名传递给 forName() 方法,而不是简单的名称。例如,我们应该将字符串 "com.baeldung.getclassfromstr.MyNiceClass" 传递给 forName() 方法。否则,forName() 方法会抛出 ClassNotFoundException

assertThrows(ClassNotFoundException.class, () -> Class.forName("MyNiceClass"));

4. 关于异常处理的一些话

我们已经了解了如何从类名获取 MyNiceClassClass 对象。为了简单起见,我们在测试中省略了异常处理。现在,让我们看看在使用 Class.forName()cls.getDeclaredConstructor().newInstance() 方法时应处理哪些异常。

首先,Class.forName() 会抛出 ClassNotFoundException。当我们仅传递 MyNiceClass 的简单名称时,我们已经提到过这一点。ClassNotFoundException 是一个检查异常。因此,在调用 Class.forName() 方法时,我们必须处理它。

接下来,让我们看看 cls.getDeclaredConstructor()newInstance()getDeclaredConstructor() 方法会抛出 NoSuchMethodException。此外,newInstance() 会抛出 InstantiationExceptionIllegalAccessExceptionIllegalArgumentExceptionInvocationTargetException。这五个异常都是检查异常。如果我们使用这两个方法,就需要处理它们。

值得一提的是,本节讨论的所有异常都是 ReflectiveOperationException 的子类型。也就是说,**如果我们不想分别处理这些异常,可以处理 ReflectiveOperationException**,例如:

void someNiceMethod() throws ReflectiveOperationException {
    Class cls = Class.forName("com.baeldung.getclassfromstr.MyNiceClass");
    MyNiceClass myNiceObject = (MyNiceClass) cls.getDeclaredConstructor().newInstance();
    // ...
}

或者,我们可以使用 try-catch 块:

try {
    Class cls = Class.forName("com.baeldung.getclassfromstr.MyNiceClass");
    MyNiceClass myNiceObject = (MyNiceClass) cls.getDeclaredConstructor().newInstance();
    // ...
} catch (ReflectiveOperationException exception) {
    // handle the exception
}

5. 总结

在这篇短文中,我们学会了使用 Class.forName() 方法从给定的类名字符串中获取 Class 对象。值得注意的是,我们需要将完整的类名传递给 Class.forName() 方法。

如往常一样,本文中的所有代码示例都可以在 GitHub 上找到。