我可以使用反射更改接口常量(JDK9 +)的值吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我可以使用反射更改接口常量(JDK9 +)的值吗?相关的知识,希望对你有一定的参考价值。

public interface A
{
    int const1 = 5;
}


Class clazz=A.class;

如何使用反射更改const1? clazz.getField(????)

答案

我可以使用反射更改接口常量(JDK9 +)的值吗?

一般来说,你不能。当然不在你的例子中。

@ CardinalSystem的答案中提供的反射技巧不适用于使用编译时常量表达式初始化的任何常量。

17.5.3. Subsequent Modification of final Fields

“即使在那时,也存在许多复杂情况。如果在字段声明中将final字段初始化为常量表达式(第15.28节),则可能无法观察到对final字段的更改,因为在编译时会替换final字段的使用时间与常量表达式的值。“

笔记:

  1. 对于当前生成的Java工具链/ JVM,“可能无法观察到”实际上是“将不会被观察到”...除非您使用反射来观察字段值。
  2. 这不适用于所有接口字段。虽然界面常量隐式为staticfinal,但它们可以使用不是常量表达式的表达式进行初始化。在这种情况下,反射技巧应该有效......只要你注意处理“内存模型问题”。

Jim Garrison和其他人提出了一个有效的观点,即你不应该做这种事情。它导致维护噩梦1。

1 - ......榆树街品种。

另一答案

您可以从使字段可访问开始:Field#setAccessible()然后使用getDeclaredField("modifiers")来获取访问修饰符,然后您可以使用Field#setInt()更改修饰符,以便您可以修改字段:

public static void main(String args[]) {

    A a = new A() {};       

    try {
        setFinalStatic(a, "const1", 2);
    } catch (Exception e) {
        e.printStackTrace();
    }


}

public static void setFinalStatic(Object parent, String fieldName, Object newValue) throws Exception {
    Field field = parent.getClass().getField(fieldName);
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    System.out.print("Before : " + field.get(parent));
    field.set(parent, newValue);
    System.out.println("	After : " + field.get(parent));
}
另一答案

您不应该尝试在运行时更改最终字段。即使您通过反射更改其值,所有使用此最终字段的类仍将保留原始常量值。

另一答案

只有你必须改变A a = new A(){};

上:

等级c = A.class;

你有接口:)

以上是关于我可以使用反射更改接口常量(JDK9 +)的值吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中,是不是可以在运行时使用反射将成员变量添加到类中?

我可以将 config.json 文件交给我的客户,以便他们可以更改其网站上的值吗?

在 Aws Lex 中 - 我们可以使用 lambda 更改槽值吗?

我可以知道哪个线程从核心转储文件中更改了全局变量的值吗?

如果可以使用复选框更改多行值?

点后的Sql值更改[重复]