我有两个 Java 9 模块、一个服务器和一个处理程序。服务器使用 ServiceLoader 加载 HTTP 处理程序(代码如下)。
为什么此代码段中的 o.getClass().getName()
有效?是因为 provides
将处理程序类打开为反射吗? getClass().getName() 不使用反射吗? Java 是否总是以某种方式将接口(interface)映射到底层类实例(从而映射到类)而不需要反射?
服务器模块代码:
ServiceLoader
.load(HTTPHandlerWithContext.class)
.stream()
.map(ServiceLoader.Provider::get)
.forEach(o -> {
System.out.printf(
"registering route %s to %s%n",
o.getContext(),
o.getClass().getName()
);
server.createContext(o.getContext(), o);
});
处理程序模块信息:
module com.example.helloworld {
requires com.example.tinyjhttpd;
requires jdk.httpserver;
provides com.example.tinyjhttpd.HTTPHandlerWithContext
with com.example.helloworld.HelloWorld;
}
我认为 Class.java 中的相关片段不足以让我清楚:
// Cache the name to reduce the number of calls into the VM.
// This field would be set by VM itself during initClassName call.
private transient String name;
private native String initClassName();
最佳答案
Java 语言规范没有详细定义反射(因此,opens
的影响或缺乏反射),而是 refers to the API specification :
[...] This specification constrains the behavior of such classes and interfaces, but does not provide a complete specification for them. The reader is referred to the Java SE Platform API documentation.
Consequently, this specification does not describe reflection in any detail. Many linguistic constructs have analogs in the Core Reflection API (
java.lang.reflect
) and the Language Model API (javax.lang.model
), but these are generally not discussed here.
Java SE Platform API 文档指定何时可以抛出 IllegalAccessException
,例如调用Field.get
或Method.invoke
.
都不是Object.getClass()
也不Class.getName()
已指定可能抛出 IllegalAccessException
。
这与引入模块系统之前Java的运行时行为是一致的。只是有关何时授予或不授予访问权限的规则变得更加复杂。
与访问内部数据或调用非 API 方法相比,能够查询类名称的影响相当低。
关于java - 为什么 getClass().getName() 对未打开的模块类起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69064624/