public class MyClass{
public void action() {
}
public void test(){
MyClassNameTest.takeAction(this::action);
}
}
public interface MyInterface {
public void action();
default void printClassName(){
System.out.println("java version: " + System.getProperty("java.version"));
System.out.println("getCanonicalName: " + getClass().getCanonicalName());
System.out.println("getName: " + getClass().getName());
System.out.println("isAnonymousClass: " + getClass().isAnonymousClass());
}
}
Run Code Online (Sandbox Code Playgroud)
运行这个类:
public class MyClassNameTest {
public static void main(String[] args) {
new MyClass().test();
}
static void takeAction(MyInterface myInterface) {
myInterface.printClassName();
myInterface.action();
}
}
Run Code Online (Sandbox Code Playgroud)
getClass().getCanonicalName()返回空值
如果您在编译时在相同的 Java 版本中运行它们,getCanonicalName()则返回一个非空字符串。
我发现了有趣的结果,但我不知道原因。有人知道吗?
经过一番调查后,这显然是因为从 Java 15 开始,方法引用和 lambda(或者更确切地说,invokedynamic)现在是使用隐藏类来实现的,至少在 OpenJDK 中是这样。简而言之,隐藏类是在运行时动态定义的类,使用Lookup.defineHiddenClass,没有二进制名称,并且不需要类加载器来加载。
也尝试打印getClass().isHidden()在printClassName. 它应该打印true。
您还可以比较Java 15 实现与InnerClassLambdaMetafactoryJava 8 实现。后者使用已弃用的sun.misc.Unsafe.defineAnonymousClass.
根据引入隐藏类(也在 Java 15 中实现)的 JEP,getCanonicalName返回 null 是预期的行为:
通过该
Class对象,可以实例化隐藏类并像普通类一样访问其成员,但有四个限制:
Class::getName返回一个不是二进制名称的字符串,如前所述。
Class::getCanonicalName返回 null,表示隐藏类没有规范名称。(请注意,ClassJava 语言中匿名类的对象具有相同的行为。)[...]
归根结底,方法引用表达式生成的对象仅具有JLS 本节中规定的保证。实现可能随时发生变化,本例就是一个例子。
| 归档时间: |
|
| 查看次数: |
323 次 |
| 最近记录: |