描述
我有一个奇怪的问题,即Method::getGenericReturnType()无法检索泛型类型信息。
这是最小化版本:
public class Test {
public static void main(String[] args) {
Method method = B.class.getMethods()[0]; // foo() method inherited from A
System.out.println(method.getGenericReturnType());
}
static class A {
public List<String> foo() { return null; }
}
public static class B extends A {}
}
输出是
java.util.List
没有任何通用类型信息。这对我来说似乎很奇怪。
但是,将A
s 可见性更改为public
并正确给出
java.util.List<java.lang.String>
问题
我不知道这是一个错误还是实际预期的行为。如果是预期的,其背后的原因是什么?
我正在使用来自 AdoptOpenJDK 的 OpenJDK 15:
// javac
javac 15.0.1
// java
openjdk version "15.0.1" 2020-10-20
OpenJDK Runtime Environment AdoptOpenJDK (build 15.0.1+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 15.0.1+9, mixed mode, sharing)
朋友也可以复制它:
- JDK祖鲁8
- 采用OpenJDK 10、11、14
发现
A
我做了很多实验,发现和之间唯一的可见性组合B
触发了这个问题是 when B
ispublic
和A
is not public
。任何其他组合,它都会再次按预期工作。所以只有
- 乙
public
,甲protected
- 乙
public
,甲package-visible
- 乙
public
,甲private
表现出奇怪的行为。
我尝试在不同的文件中移动代码,将其放入不同的包中,static
在这里和那里添加或删除,没有任何改变。
我还检查了该方法的源代码,即
public Type getGenericReturnType() {
if (getGenericSignature() != null) {
return getGenericInfo().getReturnType();
} else { return getReturnType();}
}
wheregetGenericSignature()
依赖于在实例String signature
构造过程中设置的a。Method
在上述情况下似乎是null
出于某种原因。
更新 1
我只是在检查类的字节码,并在以下位置找到了这个B.class
:
public Test$B();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method Test$A."<init>":()V
4: return
LineNumberTable:
line 16: 0
public java.util.List foo();
descriptor: ()Ljava/util/List;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #7 // Method Test$A.foo:()Ljava/util/List;
4: areturn
LineNumberTable:
line 16: 0
B
在我看来,出于某种原因,这看起来像是创建了另一个方法foo()
,该方法只是将方法调用转发给A
s foo()
,因此没有泛型类型信息。
而且,调用B.getDeclaredMethods()
它实际上返回一个方法,即
public java.util.List Test$B.foo()
即使此方法应该排除继承的方法(来自文档):
返回一个包含 Method 对象的数组,该对象反映此 Class 对象表示的类或接口的所有声明方法,包括公共、受保护、默认(包)访问和私有方法,但不包括继承方法。
B
如果真的创建了一个包装方法,那么现在这将是有意义的。
但是,它为什么要创建这样的方法?是否有解释此行为的 JLS 部分?