从包外获取对字段的包级访问权限?

时间:2009-11-12 12:40:44

标签: java field

我正在使用一个API,它有一个我希望扩展的抽象类(在我的具体类中),以便利用父类中的一些方法。不幸的是,该API类的程序员决定使用一个字段来为其提供包级访问而不使用公共setter。而是在方法中设置字段值。是否有一个共同的“桥梁模式”,以便我可以适当地设置/设置该字段?这不仅对我的功能很重要,对于测试也很重要(因为我需要模拟在我的测试中在该字段中设置的值)。谢谢!

4 个答案:

答案 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被配置为允许它 - 但这感觉就像是一点代码味道。