在Java中运行时添加final修饰符

use*_*903 18 java final modifier

听起来有点奇怪,但是可以final在运行时添加修改器吗?

我有一个标记为的变量public static int/short.在某些时候我想阻止改变它的值,我希望将其可访问性保持为标准静态值(ClassName.field).

public class Main {

    private static int a = 0;

    public static void addFinalMod(Field f) {

        Field modifiersField = null;
        try {
            modifiersField = Field.class.getDeclaredField("modifiers");
        }
        catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        modifiersField.setAccessible(true);
        try {
            modifiersField.setInt(f, f.getModifiers() & Modifier.FINAL);
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        System.out.println(a);
        try {
            Field f = Main.class.getDeclaredField("a");
            addFinalMod(f);
        }
        catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        a = 10; //I was expecting error/exception here
        System.out.println(a);
    }
Run Code Online (Sandbox Code Playgroud)

输出:

0
10
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 33

在某些时候,我想防止改变它的价值

在应用程序逻辑中这样做.使变量只能通过方法访问.保持一个标志跟踪变量的任何变化.应用更改或达到某个点后,提高标志,并为更改变量的任何进一步尝试抛出异常.

final是一种语言关键字/功能,用于编写源代码并防止在源代码中重新分配变量.在运行时,它(几乎)没有.

  • @ user2749903然后你运气不好.无法通过直接变量访问来完成.你基本上想要的是一个看起来像变量的函数,Java没有(其他语言都有,但Java没有). (7认同)
  • 即使对象本身(具有`final`字段)以非线程安全的方式发布,整洁/特殊的事情也是如此.一个典型的例子(我相信历史上的激励者)是`String`.它有一个`final char []`,但是在Java 1.5之前(当添加了这些新的`final`语义时),如果一个线程创建了一个`String`并且将它安全地发布到另一个线程,你仍然可以看到部分构造的值(例如,通过将其设置在非易失性"静态"字段中.使用这些"新"语义,如果你可以访问`String`,那么你将看到你应该完全看到`char []`. (3认同)
  • @SylvainLeroux线程安全,JLS 17.5.基本上,只要你不从构造函数中泄漏`this`引用,就可以保证从(至少)构造时的状态中的任何线程看到任何`final`字段.例如,`ArrayList`通常不是线程安全的,但是如果你有一个`final ArrayList <Foo>`你实例化并填写你的构造函数,_并且你永远不会在构造函数之后修改它,那么任何可以看到你的线程对象保证看到完全构造的`ArrayList`(包括看到它完全构造的任何对象等). (2认同)