Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.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_Bytearray_Field_.class File - Fatal编程技术网

Java 其中是存储在类文件中的变量的初始值

Java 其中是存储在类文件中的变量的初始值,java,bytearray,field,.class-file,Java,Bytearray,Field,.class File,我仍在尝试学习java类文件格式,我知道常量变量值存储在ConstantValue属性下,但是我不知道非常量字段值存储在类文件中的什么位置。比如 public Robot robot = new Robot(); 我查看了oracles类文件规范,但找不到任何类似的属性 粘贴的代码中没有常量。只有一个变量(将在运行时在堆栈上分配) 如果您对具有非常量字段的类的字节码有兴趣,可以尝试 变量robot在运行时初始化。比如说,robot正在上课Foo: class Foo { public

我仍在尝试学习java类文件格式,我知道常量变量值存储在ConstantValue属性下,但是我不知道非常量字段值存储在类文件中的什么位置。比如

public Robot robot = new Robot();

我查看了oracles类文件规范,但找不到任何类似的属性

粘贴的代码中没有常量。只有一个变量(将在运行时在堆栈上分配)

如果您对具有非常量字段的类的字节码有兴趣,可以尝试


变量
robot
在运行时初始化。比如说,
robot
正在上课
Foo

class Foo {
    public Robot robot = new Robot();
    Foo() {
    }
}
现在,Java编译器将
new Foo()
转换为一系列指令,执行以下步骤:

  • 为堆上的新对象
    Foo
    分配空间。这包括字段
    robot
    的空间
  • 跳转到类
    Foo
    • Foo初始值设定项为
      Robot的新实例分配空间
    • 调用
      Foo的父级构造函数
    • 调用
      机器人的初始值设定项
那么字节码是什么呢

  • Foo的分配和初始化说明
  • 机器人的分配和初始化说明
结论是类文件中的字节码中没有用于野外机器人的空间。有些分配指令在运行时执行,并为堆上的字段创建空间



存储初始值的唯一属性是
ConstantValue
。但是,这仅用于静态变量。在Java编译代码中,它只用于静态最终变量,尽管它可以用于手写字节码中的任何静态变量。当然,这个值必须是常数

对于您发布的示例,您拥有Java中已知的初始值设定项。这些在类文件中没有等价物。相反,Java编译器将在每次超类构造函数调用返回后粘贴此代码。请注意,这意味着如果您可以在此之前查看它们,例如通过调用超类构造函数中的虚拟方法,那么它们还没有初始化

这里有一个例子

public class initializers {

    static final float f = 4;
    static final int i = int.class.hashCode();
    static int i2 = 4;

    public final Object x = null;
    public Object x2 = null;


    public initializers() {}
    public initializers(int x) {this();}
    public initializers(float x) {}
}
编译和分解课程会导致

.version 49 0
.class super public initializers
.super java/lang/Object

.field static final f F = 4.0F
.field static final i I
.field static i2 I
.field public final x Ljava/lang/Object;
.field public x2 Ljava/lang/Object;

.method public <init> : ()V
    .limit stack 2
    .limit locals 1
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aconst_null
    putfield initializers x Ljava/lang/Object;
    aload_0
    aconst_null
    putfield initializers x2 Ljava/lang/Object;
    return
.end method

.method public <init> : (I)V
    .limit stack 1
    .limit locals 2
    aload_0
    invokespecial initializers <init> ()V
    return
.end method

.method public <init> : (F)V
    .limit stack 2
    .limit locals 2
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aconst_null
    putfield initializers x Ljava/lang/Object;
    aload_0
    aconst_null
    putfield initializers x2 Ljava/lang/Object;
    return
.end method

.method static <clinit> : ()V
    .limit stack 1
    .limit locals 0
    getstatic java/lang/Integer TYPE Ljava/lang/Class;
    invokevirtual java/lang/Object hashCode ()I
    putstatic initializers i I
    iconst_4
    putstatic initializers i2 I
    return
.end method
.version 49 0
.class超级公共初始值设定项
.super java/lang/Object
.现场静态最终f=4.0F
.field静态期末考试i
.现场静态i2 I
.field public final x Ljava/lang/Object;
.field public x2 Ljava/lang/Object;
.public方法:()V
.限制堆栈2
.限制本地人1
阿洛德0
调用特殊的java/lang/Object()V
阿洛德0
空的
putfield初始值设定项x Ljava/lang/Object;
阿洛德0
空的
putfield初始化器x2 Ljava/lang/Object;
返回
.结束方法
.方法:(一)五
.限制堆栈1
.限制本地人2
阿洛德0
调用特殊初始值设定项()V
返回
.结束方法
公共方法:(F)V
.限制堆栈2
.限制本地人2
阿洛德0
调用特殊的java/lang/Object()V
阿洛德0
空的
putfield初始值设定项x Ljava/lang/Object;
阿洛德0
空的
putfield初始化器x2 Ljava/lang/Object;
返回
.结束方法
.静态方法:()V
.限制堆栈1
.限制本地值0
getstatic java/lang/Integer类型Ljava/lang/Class;
invokeVirtualJava/lang/Object hashCode()I
putstatic初始值设定项i
iconst_4
putstatic初始值设定项i2 I
返回
.结束方法

如您所见,
f
是唯一使用
ConstantValue
属性的
i
没有,因为它不是一个常量表达式,而
i2
没有,因为它不是最终表达式。初始化
i
i2
的代码放在静态初始值设定项(“类构造函数”)中。初始化
x
x2
的代码是在两个超类构造函数调用后粘贴的,但不在第二个构造函数中,后者只调用同一类中的构造函数。

因为值如果不是常量,它不能存储在类文件中。但该变量何时初始化,则错误的变量将存储在堆栈或堆中,具体取决于声明它的位置。如果它是一个方法局部变量,那么只有它会进入堆栈,否则它会进入堆。@JunedAhsan这个问题是关于字段的,所以我假设它是一个字段,而不是局部变量。我还对答案补充了一些解释