• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Constructors

 
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i do not understand the following code
class Top {
int x;
class Dummy {
Dummy(Object o) {}
}
class Inside extends Dummy {
Inside() {
super(new Object() { int r = x; }); //1
}
Inside(final int y) {
super(new Object() { int r = y; }); }
}
}
Please explain to me exactly what is happening and how it can be resolved?
There is a compile error at line 1.
-Sanjana
 
Ranch Hand
Posts: 504
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Very good and tricky question.

The error I'm getting is "cannot reference x before supertype constructor has been called". OK, the rule of thumb for making calls to super() and this() is that you cannot supply instance members as arguments to these calls because, well, the constructor hasn't completed constructing the object yet. However, in this example, class Inside is clearly an inner class, so by the time its instance gets created, the enclosing instance must exist on the heap, and x must be initialized! I'd love to hear the opinion of somebody who knows the compiler behavior whether it's a compiler issue or a JLS limitation.
 
Ranch Hand
Posts: 400
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Does it hinge on the fact that the super class here is also the enclosing class but compiler cannot determine that?.
Often that would not be the case, so members would not be access unitl after constructor had ran.
The order of creation etc is spelled out on page 314 of Sierra and Bates.
 
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Sanjana, let's learn from something that compiles. I am going to move the anonymous class declaration.

Four class files are created.
Top$1.class, Top$Dummy.class, Top$Inside.class, Top.class
Let's disassemble the class files of Inside and the anonymous class:

Notice that the compiler adds a synthetic field this$1 to the anonymous class. It is a reference to the enclosing instance of Inside.
Notice that the compiler adds a synthetic field this$0 to the inner class Inside. It is a reference to the enclosing instance of Top.

When the anonymous subclass is instantiated, the instance variable r is initialized with x: First a reference to the anonymous object is loaded. Using that reference, the reference, this$1, to the Inside object is loaded. this$1 is passed to a static method of Inside and a reference to the Top object is returned. Using that reference, the value of x is loaded and stored in r.
Therefore, a reference to the Inside object and a reference to the Top object must be know when r is initialized to x. That is, the instance fields this$1 and this$0 must be initialized.
---
Now let's go back to your original example.
super(new Object() { int r = x; }); //1
The parameter list of the super(...) expression is called a static context. "this" cannot be used here. The instance variables of the Inside object have not been initialized. In particular, the instance field this$1 has not been initialized.
[ December 05, 2003: Message edited by: Marlene Miller ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now I will try to state simply what is happening.
An inner class can access instance variables of the directly enclosing instance only if it has a compiler-generated reference to the enclosing instance.
If an inner class is declared in a static context, it has no reference to the directly enclosing instance.
[ December 05, 2003: Message edited by: Marlene Miller ]
 
sanjana narayanan
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank u so much..The explanation is too good..

-Sanjana
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I learned about inner classes from Cay Horstmann's Core Java. He showed me how to disassemble a class file and what it means.
When I want to understand things about inner classes, and the JLS and The Java Programming Language just say the rules but not why, I almost always have to disassemble the class file.
javap -private Outer.class
javap -private Outer$Inner.class
javap -private Outer$1.class
You can see the extra fields the compiler adds. One object might have a reference to the other one. Or the local variables of one object might be copied to the other object. Or the constructor might have extra params. Think about two objects separated physically in space. It begins to make sense.
[ December 05, 2003: Message edited by: Marlene Miller ]
 
reply
    Bookmark Topic Watch Topic
  • New Topic