terje7601 schreef op donderdag 10 maart 2011 @ 09:44:
[...]
Als je 'bla' final maakt, zal je toch nog steeds "null" als output krijgen? Ik begrijp even niet wat je zegt i.v.m. de compiler...in de bytecode voor Derived.Foo() zal toch gewoon gerefereerd worden naar de member 'bla'?
Nee. 'bla' is final, dus die kan nooit aangepast worden. Hij wordt direct geïnitialiseerd, dus de compiler weet dat 'bla' altijd "hoi" is, en zal daardoor direct de string "hoi" gebruiken ipv te kijken naar de waarde van 'bla'.
Echter, het blijft een member die geïnitialiseerd moet worden, wat in de default constructor gebeurt. Dit is ook te zien aan de bytecode. Die constructor runt pas nadat de constructor van Base klaar is, dus ook pas nadat Derived.Foo() wordt aangeroepen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| class Derived extends Base{
final java.lang.String bla;
Derived();
Code:
0: aload_0
1: invokespecial #1; //Method Base."<init>":()V
4: aload_0
5: ldc #2; //String hoi
7: putfield #3; //Field bla:Ljava/lang/String;
10: return
void Foo();
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #2; //String hoi
5: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
} |
Interessant is om te zien dat als je de initialisatie van 'bla' uitstelt tot in de constructor, de compiler geen kennis heeft van de waarde van 'bla', en dan dus wel die member zal accessen, ookal is de daadwerkelijk gegenereerde constructor exact identiek.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Derived extends Base
{
final String bla;
{
bla = "hoi";
}
void Foo()
{
System.out.println(bla);
}
} |
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| Compiled from "Test.java"
class Derived extends Base{
final java.lang.String bla;
Derived();
Code:
0: aload_0
1: invokespecial #1; //Method Base."<init>":()V
4: aload_0
5: ldc #2; //String hoi
7: putfield #3; //Field bla:Ljava/lang/String;
10: return
void Foo();
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: getfield #3; //Field bla:Ljava/lang/String;
7: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
} |
[
Voor 51% gewijzigd door
.oisyn op 11-03-2011 19:55
]