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
类型。
我们的目标是根据类名获取 MyNiceClass
的 Class
对象,并且想从 Class
对象创建一个 MyNiceClass
的实例,以验证所获取的 Class
对象是否是我们想要的。
为了简化,我们将使用单元测试断言来验证我们的解决方案是否按预期工作。
接下来,让我们实际操作一下。
3. 使用 forName()
方法获取 Class
对象
Class
类提供了 forName(String)
方法,从一个字符串形式的类名获取 Class
对象。现在,让我们看看如何调用此方法获取 MyNiceClass
的 Class
对象:
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. 关于异常处理的一些话
我们已经了解了如何从类名获取 MyNiceClass
的 Class
对象。为了简单起见,我们在测试中省略了异常处理。现在,让我们看看在使用 Class.forName()
和 cls.getDeclaredConstructor().newInstance()
方法时应处理哪些异常。
首先,Class.forName()
会抛出 ClassNotFoundException
。当我们仅传递 MyNiceClass
的简单名称时,我们已经提到过这一点。ClassNotFoundException
是一个检查异常。因此,在调用 Class.forName()
方法时,我们必须处理它。
接下来,让我们看看 cls.getDeclaredConstructor()
和 newInstance()
。getDeclaredConstructor()
方法会抛出 NoSuchMethodException
。此外,newInstance()
会抛出 InstantiationException
、IllegalAccessException
、IllegalArgumentException
和 InvocationTargetException
。这五个异常都是检查异常。如果我们使用这两个方法,就需要处理它们。
值得一提的是,本节讨论的所有异常都是 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 上找到。