以下文字来自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 is
initialized to a compile-time constant expression (§15.28) in the field
declaration, changes to the final field may not be observed, since uses of that
final field are replaced at compile time with the value of the constant
expression.
Run Code Online (Sandbox Code Playgroud)
任何人都可以给我更好的解释.我无法理解这一说法changes to the final field may not be observed.可以借助例子.
提前致谢
Vis*_*l K 10
我无法理解声明对最终字段的更改可能没有被观察到
它告诉我们,如果最终变量被声明为编译时常量,那么在程序中使用反射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
}
}
Run Code Online (Sandbox Code Playgroud)
上面代码的输出是:
20
20
Run Code Online (Sandbox Code Playgroud)
为什么?
答案在于javap -cpublic 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
}
Run Code Online (Sandbox Code Playgroud)
在第16行(在changeFinal调用方法之前),将值cf.x硬编码为20.在第33行(changeFinal调用方法之后),值cf.x再次被硬编码20.因此,虽然最终变量值的变化在执行期间x成功完成 reflection API,但由于x是编译时常量,因此它显示其常量值20.
| 归档时间: |
|
| 查看次数: |
1359 次 |
| 最近记录: |