如何在java中使用反射将瞬态添加到现有类中

  • 本文关键字:添加 反射 java java reflection
  • 更新时间 :
  • 英文 :


是否有办法使用java反射API使字段静态或瞬态?

EDIT:我有一些已经使用soap api序列化的bean,并且正在被一些客户端使用,对于一些客户端,我不想暴露一个或两个字段。

当然,有很多方法可以做到这一点,而无需更改或添加瞬态关键字。

只是想知道这是否可以做到,如果可以,怎么做?

编辑:我不会把它称为API或框架问题,更像是一个设计缺陷…我将apache axis2用于soap

No。这样做需要修改类的字节码。在static字段的情况下,一个特别的困难是使用不同于对象字段的字节码访问它们。

我不明白为什么一个字段不能在运行时做transient,至少在理论上,但目前的反射API不允许它。参见:在java中,字段's瞬态属性/标志可以通过反射设置吗?

你不能用反射api这样做。我认为有一些字节码操作工具,但在这种情况下,您可以使用Decorator模式。它解决了问题,但我认为它非常丑陋:

(这里省略了常用的样板,比如接口)

public class StaticDecorator {
    private static Object staticField;
    private Object yourObject;
    public StaticDecorator(Object yourObject) {
        this.yourObject = yourObject;
    }
    public static Object getStaticField() {
        return staticField;
    }
    public static void setStaticField(Object object) {
        staticField = object;
    }
}

我使用Object作为你要包装的类的类型,当然你可以替换任何你想要的类型。使用这样的方法,你可以用一个静态字段"装饰"任何类。

如果你是真的,非常必须想要一个静态字段的对象在运行时,这可以帮助你,但我认为有一个设计缺陷潜伏在某处

您可以将bean包装在另一个bean中,该bean只公开您希望通过API公开的字段。例如,对于具有foobarbaz字段的内部bean,您不希望公开baz

Lombok Delegation可以使这非常简单,但这里有一个使用普通java的示例。

public class ExposedBean {
    private InternalBean internalBean;
    public ExposedBean(InternalBean internalBean) {
        this.internalBean = internalBean;
    }
    public String getFoo() { return internalBean.getFoo(); }
    public String getBar() { return internalBean.getBar(); }
}
public class InternalBean {
    private String foo;
    private String bar;
    private String baz;
    public String getFoo() { return foo; }
    public String getBar() { return bar; }
    public String getBaz() { return baz; }
}

原答案,关于设置修饰语

不能设置修饰符。但是,您可以检查它们。

Field myField = /* get a field object */;
if (Modifier.isTransient(myField.getModifiers()) {
    System.out.println("myField is transient.");
}
if (Modifier.isFinal(MyClass.class.getModifiers()) {
    System.out.println("MyClass is final.");
}
有了更多关于你想解决的问题的信息,我们可以提出替代方案。Member#getModifiers()没有声明为final,所以您可以使用修饰符。(下面的代码是100%未经测试的)
public class FieldModifierDecorator extends Field {
    protected Field field;
    private int modifiers = -1;
    public static void decorate(Field field) {
        FieldModifierDecorator newInstance = new FieldModifierDecorator();
        newInstance.field = field;
        return newInstance;
    }
    public void overrideModifiers(int modifiers) {
        this.modifiers = modifiers;
    }
    public int getModifiers() {
        if (-1 == modifiers) {
            return field.getModifiers();
        }
        return modifiers;
    }
}
// Example usage
public Field makeFieldAppearTransient(Field field) {
    FieldModifierDecorator decoratedField = FieldModifierDecorator.decorate(field);
    decoratedField.overrideModifiers(field.getModifiers() | Modifier.TRANSIENT);
    // if (Modifier.isTransient(decoratedField.getModifiers())) {
    //     System.out.println("It looks transient, but really isn't.");
    //}
    return decoratedField;
}

修改类信息或字节码修改绝对是错误的工具。

你想用技术手段解决一个商业问题。

听起来更像是你需要一个许可的概念。用户可能有权限查看某些字段。在此基础上,您可以使用java bean自省来清除这些字段的值,然后将它们发送到客户端。

然而,这也可能有它的问题。客户端应该能够确定它是否有权限查看该字段

相关内容

  • 没有找到相关文章

最新更新