我上课了AbstractsAndInterfaces:
public static AbstractsAndInterfaces instance = new AbstractsAndInterfaces();
private static final int DELTA = 5;
private static int BASE = 7;
private int x;
public AbstractsAndInterfaces()
{
//System.out.println(BASE);
//System.out.println(DELTA);
x = BASE + DELTA;
}
public static int getBASE()
{
return BASE;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
System.out.println(AbstractsAndInterfaces.instance.x);
}
Run Code Online (Sandbox Code Playgroud)
为什么打印5?
为什么BASE变量未初始化?
The*_*ind 10
那是因为 :
private static final int DELTA = 5;将是一个编译时常量.因此,当类初始化(加载一次)后,5已经可用(初始化).
执行的第一行是:
public static AbstractsAndInterfaces instance = new AbstractsAndInterfaces();
所以,现在你将去:
public AbstractsAndInterfaces()
{
//System.out.println(BASE);
//System.out.println(DELTA);
x = BASE + DELTA; // same as x= 0+5 i.e default value of fields + constant value 5
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,DELTA将是5但是BASE因为它不是0 final.更改BASE为final将更改结果12.
编辑:
用于显示具有字节代码的OP场景的示例代码.
public class Sample {
static Sample s = new Sample();
static final int x = 5;
static int y = 10;
public Sample() {
int z = x + y;
System.out.println(z);
}
public static void main(String[] args) {
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,当程序运行时,输出将是5和不是10.现在让我们看一下字节码.
构造函数的字节代码如下所示:
p
ublic Sample();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: aload_0
1: invokespecial #24 // Method java/lang/Object."<init>
:()V
4: iconst_5 -------> // Here 5 is used directly as it is a compile time constant
5: getstatic #20 -------> // Field y:I
8: iadd
9: istore_1
10: getstatic #25 // Field java/lang/System.out:Ljav
/io/PrintStream;
13: iload_1
14: invokevirtual #31 // Method java/io/PrintStream.prin
ln:(I)V
17: return
Run Code Online (Sandbox Code Playgroud)
静态init块的字节代码:
静态的 {}; descriptor :()V flags:ACC_STATIC代码:stack = 2,locals = 0,args_size = 0 0:new#1 // class Sample 3:dup 4:invokespecial#15 // Method"":()V 7:putstatic #18 // Field s:LSample; 10:bipush 10 12:putstatic#20 // Field y:I 15:return LineNumberTable:line 3:0 line 5:10 line 1:15 LocalVariableTable:Start Length Slot Name Signature
如果仔细检查,x则不会在类的静态init中初始化.仅y被设置为静态.但是当你查看构造函数时,你会看到常量5直接被使用(iconst_5)并被压入堆栈.
现在,如果您添加以下代码main():
public static void main(String[] args) {
System.out.println(Sample.x);
System.out.println(Sample.y);
}
Run Code Online (Sandbox Code Playgroud)
字节代码main()将是:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #25 // Field java/lang/System.out:Ljav
a/io/PrintStream;
3: iconst_5 --> // No "x" but a constant value instead of "x"
4: invokevirtual #31 // Method java/io/PrintStream.prin
tln:(I)V
7: getstatic #25 // Field java/lang/System.out:Ljav
a/io/PrintStream;
10: getstatic #20 // Field y:I --> but "y" is being fetched
13: invokevirtual #31 // Method java/io/PrintStream.prin
tln:(I)V
16: return
LineNumberTable:
line 13: 0
line 14: 7
line 15: 16
LocalVariableTable:
Start Length Slot Name Signature
0 17 0 args [Ljava/lang/String;
}
Run Code Online (Sandbox Code Playgroud)
再次观察x正在被使用,iconst_5而间接y被提取/引用.
| 归档时间: |
|
| 查看次数: |
222 次 |
| 最近记录: |