Home arrow static arrow Java Programming [Archive] - Anonymous Inner Class oddity
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - Anonymous Inner Class oddity
This topic has 31 replies on 3 pages.    1 | 2 | 3 | Next »

Posts:5,904
Registered: 04/03/99
Anonymous Inner Class oddity  
Jun 21, 2004 5:26 AM



 
Anyone feeling alert today ?

The following code is producing output of:

Hello
Fip.run(): null

But I rather expected to see:

Hello
Fip.run(): Hello

Can anyone point me to the bit of the JLS that accounts for this ?
public class TestBuild {    public static void main(String[] argv) {      String name = new String("Hello");      go(name);   }      public static void go(final String name) {      System.out.println(name);      new Fip() {         public void run() {            System.out.println("Fip.run(): " + name);         }      };   }      private abstract static class Fip {      public Fip() {         run();      }            abstract void run();   }}

Note that the following does produce the expected output, so it's the subtlety of calling the abstract method from the constructor that's escaping me.
public class TestBuild {    public static void main(String[] argv) {      String name = new String("Hello");      go(name);   }      public static void go(final String name) {      System.out.println(name);      new Fip() {         public void run() {            System.out.println("Fip.run(): " + name);         }      }.run(); // <-- Changed !   }      private abstract static class Fip {      public Fip() {         //run(); // <-- Removed !      }            abstract void run();   }}

Ouput:

Hello
Fip.run(): Hello


Both the above tested in the Sun and Eclipse compilers, with the Sun JVM, so I doubt it's a bug in anything other than my understanding.

D.
 

Posts:342
Registered: 5/22/98
Re: Anonymous Inner Class oddity  
Jun 21, 2004 5:43 AM (reply 1 of 31)



 
That's spooky, I'm using Eclipse (2.1.3) and J2SDK 1.4.2_03 and I get the expected output in both cases. What versions are you running?

Graeme
 

Posts:2,909
Registered: 13.8.2003
Re: Anonymous Inner Class oddity  
Jun 21, 2004 5:50 AM (reply 2 of 31)



 
I get

Hello
Fip.run(): null

on eclipse 2.1.3, jdk1.4.1_01 (windows 2000).

Seems like a bug then.
 

Posts:10,972
Registered: 10/23/03
Re: Anonymous Inner Class oddity  
Jun 21, 2004 5:51 AM (reply 3 of 31)



 
In any case, directly or indirectly invoking a non-final method on this in a constructor is asking for trouble.
 

Posts:1,860
Registered: 12/14/00
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:00 AM (reply 4 of 31)



 
Both the above tested in the Sun and Eclipse
compilers, with the Sun JVM, so I doubt it's a bug in
anything other than my understanding.

As a general rule, you should avoid calling overridable methods from within a constructor. This has been covered several times in the past on these forums, so you should be able to find a few relevant threads. Start with this one: http://forum.java.sun.com/thread.jsp?forum=4&thread=160236

The other thing you'll need to understand, is how local variables are synthesised as fields of local inner classes. Look at the TestBuild.Fip class file and decompile it (if you're using jad, use the -noInner flag) - If afterwards you don't understand what's going on, post back, but have a quick search of the forums first because this has been covered before.
 

Posts:1,995
Registered: 12/10/00
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:04 AM (reply 5 of 31)



 
Here is your anonymous class decompiled (javap + DJ decompiler), I bet it is clearer now...
class TestBuild$1 extends TestBuild$Fip{    private final java.lang.String val$name;    TestBuild$1(java.lang.String);    public void run() {        System.out.println("Fip.run(): " + val$name);    }}


When used in run() val$name is not yet initialized since the super() call isn't yet complete

Mike
 

Posts:5,904
Registered: 04/03/99
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:10 AM (reply 6 of 31)



 

To Kayaman and Graeme,

I'm using J2SDK 1.4.2_04 and Eclipse 3.0M9, which is interesting; I wonder which way the spec leans, or whether this is just undefined. Any pointers ?

To mattbunch & bellyripper, thanks, but I'm not intending to use this construct; I'm trying to determine where this behaviour stands with respect to the specification of the language.

D.
 

Posts:1,995
Registered: 12/10/00
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:23 AM (reply 7 of 31)



 
Well, as of the specification, all is in [url http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#41652]JLS[/url]. This chapter specifies why super() is called before initializing the instance variables, such as val$name.

Mike
 

Posts:5,904
Registered: 04/03/99
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:26 AM (reply 8 of 31)



 
But this isn't an instance variable of the anonymous inner class. It may be implemented as such, but that may be incorrect, depending on what the JLS says on this specific issue. Since I can't find a reference to this in the JLS, you're welcome to point me at it, but you can't call me a doofus until you have.

D.
 

Posts:1,995
Registered: 12/10/00
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:40 AM (reply 9 of 31)



 
And I am no longer interested in spending my time on this. Sorry. I would say more but I don't want to raise quarrels.

Mike
 

Posts:342
Registered: 5/22/98
Re: Anonymous Inner Class oddity  
Jun 21, 2004 6:53 AM (reply 10 of 31)



 
If I understand Chapter 16 (http://java.sun.com/docs/books/jls/second_edition/html/defAssign.doc.html) correctly, then IMO it is a bug. However, I may be running the risk of looking stupid here :-)

Graeme.
 

Posts:5,904
Registered: 04/03/99
Re: Anonymous Inner Class oddity  
Jun 21, 2004 7:21 AM (reply 11 of 31)



 

Ah, I missed the first para of that (read through the bit specific to anonymous classes lower down). That seems to confirm your view -

"A Java compiler must carry out a specific conservative flow analysis to make sure that, for every access of a local variable or blank final field f, f is definitely assigned before the access; otherwise a compile-time error must occur."

I wouldn't like to swear to it either (the JLS can be inscrutably subtle from time to time), but I'm emboldened by this enough to go and file a bug report & we'll see what the outcome of that is.

Dave.
 

Posts:1,995
Registered: 12/10/00
Re: Anonymous Inner Class oddity  
Jun 21, 2004 10:29 PM (reply 12 of 31)



 
It seems this thread has not changed and this makes me think that the OP posted bug report and now is waiting for some result. But I am more curious what will be the correct behaviour, how should this be implemented. Let's see what we have:

1. We have a class (yes, it's anonymous but it is a class) that overrides a run() method in its superclass. This class is TestBuild$1 that extends TestBuild$Fip. We have only class for this anonymous class - I think JLS confitms that too.

2. In the overrided version of run() we need to use a variable name that can be specified from outside. I say 'variable' because it can differ in different instances of the class that are created in each call to the go(String) method. It must be instance variable since run() accepts no parameters.

3.I see three ways to pass this variable:
- Constructor
- Setter
- Almost like setter - public(or any other access level that will work) variable

4.As we know in any of the above ways the instance variable will be initialized after the super() call and thus it will not be set in the call to run() method.

I am with DrLaszloJamf in reply 3 and think that this case is an example of this statement.

I would like to see OP's vision of the correct behaviour and the order of things that should happen.

Thanks for sharing your ideas
Mike
 

Posts:342
Registered: 5/22/98
Re: Anonymous Inner Class oddity  
Jun 21, 2004 11:16 PM (reply 13 of 31)



 
Mike,

As a matter of interest, what compiler are you using? I find it strange that I seem to be the only one who's compliler results the OPs expected result. I downloaded and used the DJ decompiler you mentioned (Thanks for that one by the way) , and the decompiler gives me back the exact code I typed. javap on my class file also doesn't show a private field declaration as yours does. If I look at the byte code (as shown by DJ) I see that the field is initialized before the constructor is called. Very strange.

Regards,
Graeme
 

Posts:342
Registered: 5/22/98
Re: Anonymous Inner Class oddity  
Jun 21, 2004 11:19 PM (reply 14 of 31)



 
Oops, thinking faster than I'm typing again, That second sentence should read:

I find it strange that I seem to be the only one who's compliler generates bytecode which produces the OPs expected result.

Graeme

 
This topic has 31 replies on 3 pages.    1 | 2 | 3 | Next »