Я недавно наткнулся на интересную ситуацию по теме порядка выполнения и поведения на заданиях переменных. Посмотрите на следующий фрагмент: < /p>
Код: Выделить всё
static class Foo {
int x = 0;
Foo() {}
}
static Foo foo = null;
public static void main(String[] args) {
System.out.println("Before foo: " + foo);
foo.x = setupFoo();
System.out.println("After foo.x: " + foo.x);
}
static int setupFoo() {
foo = new Foo();
foo.x = 1;
System.out.println("Setup foo.x: " + foo.x);
return 2;
}
< /code>
Выход: < /p>
Before foo: null
Setup foo.x: 1
Exception in thread "main" java.lang.NullPointerException:
Cannot assign field "x" because "Test.foo" is null
наблюдение
Теперь я бы ожидал, что это будет сразу же на Foo.x = Setupfoo () , потому что Foo wo Code> wonto what yullo what yullo what yullo what yullo> wo nuully , потому что foo no what nut outaly , потому что Foo wom Code wone> nuulatom Вообще не бросается, потому что setupfoo () правильно настроена экземпляры foo = new foo () .
Но по какой -то причине он делает микс. Он входит в метод, несмотря на то, что Foo Null , когда foo.x = setupfoo () , затем полностью проходит через setupfoo () , что будет настроено правильно . Но затем, возвращаясь к Main , он сбои, говоря, что foo - это null - что это было изначально, но больше не является. Какие части в JLS приходят здесь?
Код: Выделить всё
javap -vКод: Выделить всё
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #7 // Field foo:LTest$Foo;
3: invokestatic #13 // Method setupFoo:()I
6: putfield #17 // Field Test$Foo.x:I
9: return
LineNumberTable:
line 10: 0
line 11: 9
static int setupFoo();
descriptor: ()I
flags: (0x0008) ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: new #18 // class Test$Foo
3: dup
4: invokespecial #23 // Method Test$Foo."":()V
7: putstatic #7 // Field foo:LTest$Foo;
10: getstatic #7 // Field foo:LTest$Foo;
13: iconst_1
14: putfield #17 // Field Test$Foo.x:I
17: iconst_2
18: ireturn
LineNumberTable:
line 14: 0
line 15: 10
line 16: 17
< /code>
Если я понимаю это правильно, кажется, что поведение в основном объясняется этим битом здесь: < /p>
0: getstatic #7 // Field foo:LTest$Foo;
3: invokestatic #13 // Method setupFoo:()I
6: putfield #17 // Field Test$Foo.x:I
- Получает ссылку на поле foo для назначения (в настоящее время null )
- Затем вызовы setupfoo () и процессы, выполняя Fool nonlu foo.x Но ссылка foo была помещена в стек перед вызовом метода, так что он все еще null в этом контексте
Подробнее здесь: https://stackoverflow.com/questions/796 ... tion-order