gpt4 book ai didi

Java final 字段编译时常量表达式

转载 作者:搜寻专家 更新时间:2023-10-31 08:17:14 25 4
gpt4 key购买 nike

以下文字来自jls http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3

Even then, there are a number of complications. If a final field isinitialized to a compile-time constant expression (§15.28) in thefield declaration, changes to the final field may not be observed,since uses of that final field are replaced at compile time with thevalue of the constant expression.

任何人都可以给我更好的解释以上内容。我无法理解“可能无法观察到对 final 字段的更改” 这句话。可以借助示例。

最佳答案

I couldn't understand the statement changes to the final field may not be observed

它告诉我们,如果一个最终变量被声明为编译时常量,那么在程序中进一步使用反射 API 对最终变量所做的任何更改在执行期间将对程序不可见。
例如考虑下面给出的代码:

import java.lang.reflect.*;
class ChangeFinal
{
private final int x = 20;//compile time constant
public static void change(ChangeFinal cf)
{
try
{
Class clazz = ChangeFinal.class;
Field field = clazz.getDeclaredField("x");
field.setAccessible(true);
field.set(cf , 190);//changed x to 190 for object cf
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args)
{
ChangeFinal cf = new ChangeFinal();
System.out.println(cf.x);//prints 20
change(cf);
System.out.println(cf.x);//prints 20
}
}

以上代码的输出是:

20
20

为什么?
答案在于 javap -c 命令为 public static void main 提供的输出:

public static void main(java.lang.String[]);
Code:
0: new #3; //class ChangeFinal
3: dup
4: invokespecial #11; //Method "<init>":()V
7: astore_1
8: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: invokevirtual #13; //Method java/lang/Object.getClass:()Ljava/lang/Cla
ss;
15: pop
16: bipush 20
18: invokevirtual #14; //Method java/io/PrintStream.println:(I)V
21: aload_1
22: invokestatic #15; //Method change:(LChangeFinal;)V
25: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
28: aload_1
29: invokevirtual #13; //Method java/lang/Object.getClass:()Ljava/lang/Cla
ss;
32: pop
33: bipush 20
35: invokevirtual #14; //Method java/io/PrintStream.println:(I)V
38: return

}

在第 16 行(在调用 changeFinal 方法之前)cf.x 的值被硬编码为 20 。在第 33 行(调用 changeFinal 方法后)cf.x 的值再次被硬编码为 20。因此,虽然final变量x的值的改变是在执行过程中通过反射API成功完成的,但是由于x是编译时的constant 它显示其常量值 20

关于Java final 字段编译时常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17506329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com