有没有办法使用 java 反射 API 使字段静态或瞬态。
编辑:我有一些 Beans 已经使用soap api 序列化并且正在被一些客户使用,对于一些客户我不想公开一两个字段。
当然,有很多方法可以在不更改或添加瞬态关键字的情况下做到这一点。
只是想知道它是否可以完成,如果可以,怎么做?
编辑:我不会将其称为 API 或框架问题,更像是设计缺陷......我正在使用 apache axis2 for soap
有没有办法使用 java 反射 API 使字段静态或瞬态。
编辑:我有一些 Beans 已经使用soap api 序列化并且正在被一些客户使用,对于一些客户我不想公开一两个字段。
当然,有很多方法可以在不更改或添加瞬态关键字的情况下做到这一点。
只是想知道它是否可以完成,如果可以,怎么做?
编辑:我不会将其称为 API 或框架问题,更像是设计缺陷......我正在使用 apache axis2 for soap
不,这样的事情需要修改类的字节码。字段的一个特别困难static
是使用与对象字段不同的字节码来访问它们。
我不明白为什么不能transient
在运行时创建字段,至少在理论上是这样,但当前的反射 API 不允许这样做。另请参阅:可以通过 java 中的反射设置字段的瞬态属性/标志吗?
你不能用反射 api 来做到这一点。我认为有一些字节码操作工具,但在这种情况下,您可以使用装饰器模式。它解决了问题,但我认为它非常难看:
(我从这里省略了通常的样板,例如接口)
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 公开的字段。例如,对于带有字段foo
、bar
和的内部 bean baz
,您不想在其中公开baz
。
Lombok 委托可以使这非常简单,但这里有一个使用普通 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()
未声明为最终的,因此您可以使用装饰器。(以下代码 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 内省来清除这些字段的值。
然而,这也可能有它的问题。客户端应该能够确定它是否有权查看该字段。