| Author |
Inner class strange behavior
|
Sun LiWei
Ranch Hand
Joined: Aug 10, 2002
Posts: 49
|
|
Output: new Outer$Inner1: foo=Outer.foo bar=Inner1.bar new Outer$Inner2: foo=null java.lang.NullPointerException at Outer.access$100(JavaTest.java:1) at Outer$Inner2.getBar(JavaTest.java:37) at Outer$Inner1.<init>(JavaTest.java:14) at Outer$Inner2.<init>(JavaTest.java:29) at Outer.<init>(JavaTest.java:6) at Outer.main(JavaTest.java:43) I can't explain the null situation here. why NullPointerExceptin is thrown??? why foo is null in Inner2 class?what is the initiating order of a java class ??
|
 |
Vlado Zajac
Ranch Hand
Joined: Aug 03, 2004
Posts: 244
|
|
Constructor of Inner2 calls constructor of Inner1 before initialization of Inner2.foo so when the Inner1 constructor calls getFoo (from Inner2) it returns null. The NullPointerException is thrown because Inner2's hidden reference to Outer is also initialized after Inner1 constructor so getBar (from Inner2) calls null.access$100() (the hidded reference is null). I believe that this hidden method is used to retrieve value of bar from Outer class.
|
 |
Vlado Zajac
Ranch Hand
Joined: Aug 03, 2004
Posts: 244
|
|
In Outer foo and bar are private so to access them from inner classes the compiler creates special methods access$000 and access$100.
|
 |
marc weber
Sheriff
Joined: Aug 31, 2004
Posts: 11343
|
|
I agree with Vlado... When you attempt to create an instance of Inner2 (which extends Inner1), the constructor of Inner1 is called before instance variables of Inner2 are initialized. Within the Inner1 constructor, getFoo() is called. This is invoking the overridden method in Inner2 (which you'll see if you add a println to the method), which is trying to access the foo variable in Inner2, which is not yet initialized. That explains the null. If you comment out the bar declaration in Inner1, you will see that Outer.bar has been initialized before the exception is thrown. However, making Outer.bar static allows the program to run. Therefore, it makes sense that Inner2 simply does not yet have its reference to Outer (which it needs regardless of whether Outer.bar is private).
|
"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer
sscce.org
|
 |
Sun LiWei
Ranch Hand
Joined: Aug 10, 2002
Posts: 49
|
|
So,is the initiating order of a inner class is 1)super() 3)the hidden reference to the outter class(maybe here) 2)instance variable(s) 3)the hidden reference to the outter class(also maybe here) 4)it's own constructor This hidden reference is the thing i don't know before.when exactly this reference is initialized?
|
 |
marc weber
Sheriff
Joined: Aug 31, 2004
Posts: 11343
|
|
Well, this is a tangled web of partially constructed objects and polymorphism among inner classes. But I believe the outer reference is available to the extended inner class when super() returns. In my test code below, I've commented the NullPointerExceptions. Here's what I think is happening... We're trying to make an Outside object. In the process of initializing the members, we try to make an instance of an inner class that extends another inner class. So the constructor of the extended class implicitly calls the constructor of its parent class. Within the constructor of that parent class, a method is called (via polymorphism) in the not-yet-constructed extended class. And that method attempts to reference a variable of the outer class. This is where the problem occurs (regardless of whether that variable is private). However, if we simply comment out the polymorphic method call in the inner parent constructor and allow the extended constructor's super() to return, then we're okay. The constructor of the extended class is then able to access the variable in the outer class. NOTE: I was only able to do this with inner class constructors calling polymorphic methods that reference outer class variables. I was unable to reproduce the problem in a simpler context. [ September 11, 2004: Message edited by: marc weber ]
|
 |
 |
|
|
subject: Inner class strange behavior
|
|
|