最近我遇到了一个奇怪的行为,我维护一个应用程序。源代码版本为1.6_33,但运行于1.7u21以下。客户决定在没有咨询的情况下更改版本,我对他们的选择没有影响。为什么PropertyDescriptor和Reflection在1.6中与泛型不一样?
在架构中,某些接口在特定条件下被参数化以限制其使用。参数化的具体类必须使用定义的具体参数之一。为了方便起见,PropertyDescritor被负责实例化ConcreteParameter(用于其他进程)的机制使用。这种行为与第6版效果不错,但没有更多的与版本7
第7版,试图获取类的参数时,返回类型总是型参数的,而在6个版型是ConcreteParameter。在java中发生一个异常,并在下面的示例中介绍。但为什么在这种情况下工作?!
我浏览了JLS 7和java 7 compatibility,但未发现此行为的任何解释。对我来说,这是不合逻辑的,而不是具体的类型。有人能解释我为什么会发生这种情况?这不是一个错误,反射与getDeclaredMethod(...)一起使用,但不与getDeclaredMethods()一起使用?
在此先感谢。
下面的例子说明了什么工作由过去:
package fr.free.naoj;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
public class PropertyDescriptorAndReflectionTest {
@Test public void testPropertyDescriptorInnerWithJava7() {
PropertyDescriptor pd;
try {
// Fails
pd = new PropertyDescriptor("parameter", ConcreteClass.class);
assertEquals(ConcreteParameter.class, pd.getPropertyType());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test public void testReflectionOnGenericClassWithJava7() {
try {
// Works
Method m = ConcreteClass.class.getDeclaredMethod("getParameter", new Class<?>[]{});
m.setAccessible(true);
assertEquals(ConcreteParameter.class, m.getReturnType());
// Fails
for (Method me : ConcreteClass.class.getDeclaredMethods()) {
me.setAccessible(true);
if (me.getName().equals("getParameter")) {
assertEquals(ConcreteParameter.class, me.getReturnType());
}
}
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
private class ConcreteClass extends AbstractClass<ConcreteParameter> {
@Override public ConcreteParameter getParameter() {
this.parameter = new ConcreteParameter();
return this.parameter;
}
@Override public void setParameter(ConcreteParameter parameter) {
this.parameter = parameter;
}
}
private abstract class AbstractClass<P extends Parameter> implements Super<P> {
protected P parameter;
}
private interface Super<P extends Parameter> {
P getParameter();
void setParameter(P parameter);
}
private class ConcreteParameter implements Parameter {
@Override public String sayHello() {
return "hello";
}
}
private interface Parameter {
String sayHello();
}
}
感谢rxg为您的审查和答案。事实上,getDeclaredMethod和getDeclaredMethods的行为似乎是合乎逻辑的。 而且我也会向Oracle汇报。 – Naoj