Java字节码最终字段赋值(jasmin)

时间:2016-02-10 15:27:11

标签: java field bytecode final jasmin

在java语言中,final字段在初始化时立即获取值,不能再更改。 在java字节码(jasmin)中,如果我创建一个final字段,它会忽略我在初始化时分配的立即值,我可以像以后的任何其他变量一样更改它。

实施例。 java代码:

public class App{
    final int CONST = 2;
    App(){
        CONST = 3;
    }
    public static void main(String[] args){
        App app = new App();
    }
}

输出:

App.java:4 error: cannot assign a value to final variable CONST

实施例。 jasmin字节码:

.class App
.super java/lang/Object

.field private final CONST I = 2 ;!!! the immediate value is ignored, 0 assigned

.method public <init>()V
    .limit stack 3
    .limit locals 1
    aload_0
    invokespecial java/lang/Object/<init>()V

    aload_0
    bipush 3
    putfield App/CONST I ;!!! overwritting final field

    return
.end method

.method public static main([Ljava/lang/String;)V
    .limit stack 1
    .limit locals 1

    new App
    invokespecial App/<init>()V

    return
.end method

输出:

Generated: App.class

没有错误?我还测试了打印出新的CONST值,它就像普通变量一样工作。为什么最终字段不像在java代码中那样工作?

1 个答案:

答案 0 :(得分:2)

Java语言强制执行许多在字节码级别未强制执行的约束。其中一个是处理最终字段。

在Java字节码中,对最终字段的唯一约束是不能在<clinit>方法之外分配静态最终字段,并且不能在<init>方法(即构造函数)之外分配非静态最终字段。 / p>

您可以指定最终字段0,1,2或任意次数。如果你链接构造函数,你可以在一个构造函数中分配它,然后在不同的构造函数中覆盖它。

要了解有关字节码如何工作的更多信息,您应该阅读JVM规范。

在旁注中,尽管语法看似相似,但以下内容完全不同。

final int CONST = 2;

.field private final CONST I = 2 ;!!! the immediate value is ignored, 0 assigned

在第一个例子中,这是一个(非静态)初始化器。所有初始化程序的主体实际上只是复制到每个构造函数中。因此,您可以获得与在构造函数中编写CONST = 2时相同的效果。

相比之下,Jasmin语法正在创建ConstantValue属性。这通常用于给出静态最终字段的初始值。它可以为任何字段指定,但对于非静态字段会被忽略,因此您会看到忽略该值的原因。