我正在使用一个API,它有一个我希望扩展的抽象类(在我的具体类中),以便利用父类中的一些方法。不幸的是,该API类的程序员决定使用一个字段来为其提供包级访问而不使用公共setter。而是在方法中设置字段值。是否有一个共同的“桥梁模式”,以便我可以适当地设置/设置该字段?这不仅对我的功能很重要,对于测试也很重要(因为我需要模拟在我的测试中在该字段中设置的值)。谢谢!
答案 0 :(得分:4)
一些可能性:
获取并修改“API”的源代码。
在同一个软件包中编写一个类,以便潜入访问并公开您需要的字段。
围绕API的类编写一个包装器,提供对您所喜欢的任何更改语义的访问。
使用反射来破坏API类的访问保护。
答案 1 :(得分:1)
您将不得不使用反射来设置字段。要设置字段,请在其上调用setAccessible
。我没有对此进行过测试,但以下内容应该有效:
ClassWithProtectedField o = new ClassWithProtectedField();
Class c = o.getClass();
java.lang.reflect.Field protectedField = c.getField("protectedField");
protectedField.setAccessible(true);
protectedField.set(o, someValue);
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Field.html
答案 2 :(得分:0)
如果您可以控制SecurityManager
或者没有“{1}}”,则可以使用“反射”使字段可访问,然后更改其值。
示例代码:
import java.lang.reflect.Field;
public class ModifyProtectedFieldSample {
public static void setProtectedField(final Object targetClass,
final String fieldName,
final Object value) {
try {
final Field field = targetClass.getClass().getDeclaredField(fieldName);
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(targetClass, value);
} catch (NoSuchFieldException e) {
System.out.println("NoSuchFieldException " + e);
} catch (SecurityException e) {
System.out.println("SecurityException"+ e);
} catch (IllegalAccessException e) {
System.out.println("IllegalAccessException"+ e);
}
}
public static void main(final String[] args) {
setProtectedField(String.class, "someFieldName", Boolean.FALSE);
}
}
答案 3 :(得分:0)
如果能够,您可以在原始包中创建API类的子类,并公开显示该字段。如果你不能这样做那么你可能会使用反射来修改字段的值,假设你的SecurityManager被配置为允许它 - 但这感觉就像是一点代码味道。