【发布时间】:2019-12-07 21:26:57
【问题描述】:
我不得不承认这更像是一个表面问题,但我还没有找到更直接的解决方案这一事实让我觉得我可能遗漏了一些东西。
问题是,我的类(比如说 Foo)有一个非常重要的 static 块,它使用 Map 中的构建器方法注册自己 (Foo.class),如下所示:
// somewhere in the class
static {
Bar.registerBuilder(Foo.class, Foo::build);
}
这使得从Bar 类中获取Foo 构建器成为可能,有点像这样:
// somewhere in a method
Foo foo = Bar.getBuilder(Foo.class).apply("Hello World");
(如果构建器采用String 参数)。但是,上面的代码示例仅在 Foo 类已经初始化的情况下才有效。如果没有,这意味着Foo 的static 块没有被执行,并且构建器现在没有在Bar 中注册,这导致getBuilder() 返回null 和apply() 抛出一个@ 987654338@.
感谢互联网(主要是 StackOverflow),我发现您可以强制使用 Class.forName(String)。但真正让我困惑的是,这个方法需要一个String(因此抛出检查的ClassNotFoundException),我还没有找到一种方法来直接通过java.lang.Class 实例加载和初始化一个类。我本来期望像
Class<Foo> clazz = Foo.class;
clazz.load(); // does not exist
相反,我必须这样做:
Class<Foo> clazz = Foo.class;
try {
Class.forName(clazz.getName());
} catch (ClassNotFoundException) {
// handle an exception that is actually unreachable
}
我想知道我是否完全遗漏了什么,或者如果没有,是否有更简洁的方法可以通过java.lang.Class 表示来加载和初始化一个类。
感谢您的帮助,谢谢!
编辑 1:正如@Boris the Spider 在 cmets 中指出的那样,Foo.class 可能已经加载并初始化了该类,但它没有(至少在我的情况下)这就是我什至遇到这个问题的原因.
编辑2:使用“复杂”的方式通过Class.forName()(如代码示例)加载类实际上解决了我想的问题。只是如果可能的话,我想使用一种更清洁的方式。
使用:
- Java 11 (openjdk 11.0.2)
- IntelliJ IDEA Ultimate (2019.3)
- Maven (3.6.3)
【问题讨论】:
-
@Boris the Spider 实际上,这正是我第一次想到为什么没有
java.lang.Class.load()。但问题是我最初遇到这个问题是因为我试图从Bar获取构建器,但我得到了所说的NullPointerException。显然,Foo.class不会在 java 11 (openjdk11.0.2) 中加载Foo(或不初始化它)。我也很困惑,但这基本上是我问题的根本原因。 -
ServiceLoader 负责处理这种情况。
-
@BoristheSpider 初始化与加载完全不同,因此只能在加载之后进行,因为它需要加载的类。虽然有意未指定类加载时间,但初始化时间为precisely specified。不,使用文字
Foo.class不在此列表中。
标签: java class reflection initialization