Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中的运行时添加最终修饰符_Java_Final_Modifier - Fatal编程技术网

在Java中的运行时添加最终修饰符

在Java中的运行时添加最终修饰符,java,final,modifier,Java,Final,Modifier,听起来可能有点奇怪,但是否可以在运行时添加final修饰符 我有一个标记为公共静态int/short的变量。在某一点上,我希望防止更改其值,并希望将其可访问性保持为标准静态值(ClassName.field) 输出: 0 10 在某些情况下,我希望防止更改其值 在应用程序逻辑中这样做。使变量只能通过方法访问。保持标记跟踪变量的任何更改。应用更改或达到某一点后,升起标志,并引发异常,以备以后尝试更改变量时使用 final是一种语言关键字/功能,用于编写源代码并防止在源代码中重新分配变量。在运行时

听起来可能有点奇怪,但是否可以在运行时添加
final
修饰符

我有一个标记为
公共静态int/short
的变量。在某一点上,我希望防止更改其值,并希望将其可访问性保持为标准静态值(
ClassName.field

输出:

0
10
在某些情况下,我希望防止更改其值

在应用程序逻辑中这样做。使变量只能通过方法访问。保持标记跟踪变量的任何更改。应用更改或达到某一点后,升起标志,并引发异常,以备以后尝试更改变量时使用


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

使用不可变对象:

public class Thing {
    private int value;
    public Thing(int value) { this.value = value; }
    public int getValue() { return this.value; }
}
然后在需要修改时更换:

Thing x = Thing(1);
// do some stuff
x = Thing(2);
// more stuff
如果你在想,“但是他们仍然可以通过替换对象来修改值!”当然可以。防止这种情况发生的唯一方法是锁定某个全局状态(如果它不是常数,则实际上是不可能的),但您没有使用全局状态,对吗?全球状态是件坏事

全局状态有一个非常简单的问题:它使代码的可重用性大大降低,并且更容易出错。如果在运行时修改全局状态,则更容易出错。“噢,糟了,事情发生的顺序不对。”你不知道这有多容易。尝试跟踪事件的顺序是多线程如此困难的原因。就可重用性而言,这意味着您不能拥有该事物的两个独立实例,这反过来意味着您不能真正拥有依赖于它的任何事物的任何两个实例(至少当它最终证明您需要改变该事物时)

即使这不是一个全局性的,那么这是一种奇怪的状态,每个必须修改代码的人(包括你自己)在进行更改时都必须注意和思考。这听起来是让改变变得更容易还是更难?(提示:后者)不要对自己或同事这样做。让它更简单。从“简单胜于复杂”中吸取教训


所以,底线是:如果您需要一个不可变对象,请使用一个不可变对象。如果您需要一个非常量的不可变全局变量,请找出一种更好的方法来组织代码。

实际上,这是一个非常有趣的问题。现在,对我来说,
final
规则似乎只在编译时检查(这包括初始化要求和JMM保证)。我想你的意思是
f.getModifiers()| Modifier.final
而不是
f.getModifiers()&Modifier.final
,让其他修饰符保留。如果您将使用
f.set(null,5)您将获得预期的异常。这也是我将要做的,尽管我希望看到一个真正的解决方案,但我怀疑它是否可能。我知道,此解决方案将起作用,并且非常容易实现。但是我宁愿不使用任何方法。@user2749903那么你就不走运了。无法使用直接变量访问完成。您基本上想要的是一个看起来像变量的函数,Java没有(其他语言有,但Java没有)。@SylvainLeroux Thread safety,JLS 17.5。基本上,只要不泄漏构造函数中的
this
引用,任何
final
字段都保证可以从任何线程(至少)看到它在构造时的状态。例如,
ArrayList
通常不是线程安全的,但是如果您有一个实例化并填充在构造函数中的
最终ArrayList
,并且您从不在构造函数之后修改它,那么任何可以看到对象的线程都保证看到完整构造的
ArrayList
(包括查看它所保存的完整构造的任何对象等)。最简洁/特别的是,即使对象本身(具有
final
字段)以非线程安全的方式发布,这也是正确的。一个典型的例子(我相信历史上最有激励作用的例子)是
字符串
。它有一个
final char[]
,但在Java 1.5之前(当添加这些新的
最终
语义时),如果一个线程创建了
字符串并将其非安全地发布给另一个线程(例如,通过在非易失性
静态
字段中设置),您仍然可以看到部分构造的值语义,如果您可以访问该
字符串
,那么您将看到您应该看到的
char[]
Thing x = Thing(1);
// do some stuff
x = Thing(2);
// more stuff