use*_*818 7 java static nullpointerexception
我在互联网上找到了这个代码,并希望有人向我解释...
public class Foo {
static int fubar = 42;
public static void main(String[] args) {
System.out.println(((Foo) null).fubar);
}
}
Run Code Online (Sandbox Code Playgroud)
此代码编译并正常工作,输出结果42.
怎么可能fubar从一个null没有抛出变量的情况下访问变量NullPointerException?
dle*_*lev 10
它实际上并不是在寻找字段null,因为静态方法和字段不需要实例.强制类型表达式的类型Foo,并且fubar是一个已知的静态字段Foo,因此编译器和JVM没有问题.
通常情况下,您可以通过说出来访问该字段Foo.fubar.但是,Java足以提供一个快捷方式:如果您尝试在给定类型的实例表达式上访问静态字段或方法,它会将其视为您所说的[SomeType].theField.这就是这里发生的事情.
由于该字段fubar已声明static,因此实际命名的任何地方都只有一个字段Foo.fubar。每个实例Foo共享这个副本。当您从对象中访问此字段时Foo,Java 不会尝试按照对象引用来查找它。相反,它在专门定义的位置查找对象,该位置可以独立于任何引用进行访问。因此,如果您尝试查找null对象的该字段,则可以这样做而不会导致任何类型的NullPointerException,因为该对象从未被引用。
编辑:字节码绝对是有序的!给定这个源文件:
public class Foo {
static int fubar;
public Foo() {
((Foo)null).fubar = 137;
}
}
Run Code Online (Sandbox Code Playgroud)
这是生成的字节码:
0: aload_0
1: invokespecial #1; //Method Object."<init>":()V
4: aconst_null
5: checkcast #2; //class Foo
8: pop
9: sipush 137
12: putstatic #3; //Field fubar:I
15: return
Run Code Online (Sandbox Code Playgroud)
请注意,第 12 行使用putstatic操作码,它将值存储到static字段中。它不引用任何类型的接收者对象。事实上,如果您注意到的话,生成的字节码(第 4-8 行)会对nullto进行强制转换Foo,但随后立即发出一个pop操作码将其从堆栈中弹出。它从未在字节码中的其他任何地方被引用。
| 归档时间: |
|
| 查看次数: |
440 次 |
| 最近记录: |