gpt4 book ai didi

java - Java 对继承方法的反射(reflection)在 Windows 和 Linux 中是否不同?

转载 作者:可可西里 更新时间:2023-11-01 09:46:59 24 4
gpt4 key购买 nike

在为持续集成测试(在 JeOS 服务器上)设置 Hudson 时,我遇到了一些奇怪的行为,我希望 SO 的优秀人员可以向我解释。

我们的单元测试在很大程度上依赖于域对象的使用,其中有许多必须设置的属性(由于数据库中的空约束)。为了保持我们的测试可读性,我们创建了一个类 InstantiationUtils ,它可以实例化一个对象并通过反射设置一系列属性:

public static <T> T newInstance(final Class<T> type, final KeyValuePair<?>... propertyValues) {

return ReflectionUtils.reflectionOperation(new ReflectionOperation<T>() {

@Override
public T perform() throws Exception {

T object = type.newInstance();
for (KeyValuePair<?> propertyValue : propertyValues) {

String propertyName = propertyValue.getKey();
Object value = propertyValue.getValue();
String setterName = "set" + StringUtils.capitalize(propertyName);
ReflectionUtils.invoke(object, setterName, value);
}
return object;
}
});
}

public static void invoke(final Object target, final String methodName, final Object... params) {

List<Class<?>> parameterTypes = ListUtils.map(asList(params), "class");
Class<?> targetClass = target.getClass();
Method method = MethodUtils.getMatchingAccessibleMethod(targetClass, methodName,
parameterTypes.toArray(new Class<?>[] {}));
invoke(target, method, params);
}

public class Foo {
private String foo;

public void setFoo(final String foo) {
this.foo = foo;
}
}

public class Bar extends Foo {
private String bar;

public void setBar(final String bar) {
this.bar = bar;
}
}

不幸的是,编写这段代码的人不再为我们工作,但据我所知,它没有任何问题。对于 Windows 也是如此 - 我们在整个单元测试中都使用 InstantiationUtils,没有任何问题。

然而,Linux 是不同的。事实证明,在 Linux 中,newInstance() 方法仅适用于我们要实例化的类的直接(即非继承)成员。

InstantiationUtils.newInstance(Bar.class, "bar", "12345");将工作,而 InstantiationUtils.newInstance(Bar.class, "foo", "98765");将在 Linux 上失败,但有以下异常(exception):

xxx.xxx.xxx.ReflectionUtils$ReflectionException: java.lang.NoSuchMethodException: Property 'foo' has no setter method

在 Windows 上,这两个调用都可以工作(我知道 newInstance 签名不匹配;我们有几个重载的 newInstance() 方法可以将参数转换为 KeyValuePairs)。

我很难接受继承的公共(public)方法受到不同对待,所以我用我能想到的所有方式对此进行了测试。并且总是得出这样的结论:在Linux下,至少通过上面的Reflection用法,我们不能访问public inherited methods。

在 Windows 上,我使用 Sun 的 JRE 1.6.0.11,在 Linux 中它也是 Sun,但版本是 1.6.0.7。

谁能证实这是否正确?还是反射的使用存在某种缺陷?

最佳答案

您正在使用 MethodUtils,它有一些 limitations :

Known Limitations

Accessing Public Methods In A Default Access Superclass

There is an issue when invoking public methods contained in a default access superclass. Reflection locates these methods fine and correctly assigns them as public. However, an IllegalAccessException is thrown if the method is invoked.

另外要检查的是setFoo()方法是否重载,这也可能导致问题...

关于java - Java 对继承方法的反射(reflection)在 Windows 和 Linux 中是否不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/625516/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com