wood burning stoves 2.0*
The moose likes Java in General and the fly likes static inner classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "static inner classes" Watch "static inner classes" New topic
Author

static inner classes

Kev D'Arcy
Ranch Hand

Joined: Jul 26, 2001
Posts: 75
Is there only ever one instance of a static inner class and it's associated private (non-static) variables? Or is there a new instance created each time it's constructor is called?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
A new instance of the nested class is created each time its constructor is called. This does not require any instances of the enclosing top-level class (for a static nested class, that is).
[ January 15, 2003: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
Kev D'Arcy
Ranch Hand

Joined: Jul 26, 2001
Posts: 75
Even if it's a static class?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Yes.
The semantic of the static keyword in this case is simply that the nested class doesn't need a reference to the outer class.
In contrast, you always need an instance of the outer class to instanciate a non-static inner class.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Well, not quite:

Here we have an anonymous class which (according to the JLS) is not static, but is in a static context (inside a static menthod). Clearly it has no instance of the enclosing class Outer. So in inner (meaning, non-static) class may have an enclosing instance - and in fact, usually has one. But there are exceptions.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Oops, ok - there is always something new to learn... :roll:
Thanks for the pointer, Jim!
Garrett Smith
Ranch Hand

Joined: Jun 27, 2002
Posts: 401

Output:


Output:

The anonymous Runnable instance in OuterB is non-static? Why is the output saying that "this" is an outerB$1? Does "this" refer to the Thread t?
I'm kind of losing focus w/JLS. It's terse and examples are sparse.


comp.lang.javascript FAQ: http://jibbering.com/faq/
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
The anonymous Runnable instance in OuterB is non-static?
Correct. It's not explicitly or implicitly declared static, but it's declared in a static context. Which means it's sorta like a static class in some ways, and sorta not, in others. The JLS named it this way just to confuse us.
Why is the output saying that "this" is an outerB$1? Does "this" refer to the Thread t?
"this" is the instance of the anonymous Runnable class you've defined - inside any inner class, "this" is an instance of the innermost of all possible classes you could be talking about. (Even with multiply-nested classes.) To refer to the "this" of an outer class while inside an inner class, you'd have to use OuterClassName.this.
I'm kind of losing focus w/JLS. It's terse and examples are sparse.
Yup. It's not good to learn from in most cases - but for really esoteric stuff there's not really any other online reference I can post a link to that explains more clearly. You might want to check out the book Java Rules - as I recall it has some good discussion of this stuff. (My copy is in another state right now, so I can't check.) See also Map's review. It functions as a sort of companion to and commentary on various parts of the JLS and APIs. Might be just what you need.
[ January 26, 2003: Message edited by: Jim Yingst ]
Garrett Smith
Ranch Hand

Joined: Jun 27, 2002
Posts: 401
To refer to the "this" of an outer class while inside an inner class, you'd have to use OuterClassName.this.

I didn't know that. Of course, this can not apply here.

"An instance of inner class I whose declaration occurs in a static context has no lexically enclosing instances [JLS 8.1.3].

Another interesting piece:

Output:

It is interesting because value is hidden as an instance variable. OuterC instance is hidden inside of the anonynmous Runnable, but if you comment out this line:, then the output changes.
Here is the modified code:


value is referred from the enclosing instance of OuterC, but what I find odd is that the instance is the anonymous inner Runnable.
I'm sort of confused by OuterClassName.this. It's counterintuitive because OuterClassName is a reference to a class, right?. How can I get a reference to an instance? More to the point, how does OuterClassName.this work?
[ January 26, 2003: Message edited by: Garrett Smith ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Of course, this can not apply here.
Right. I meant "if (hypothetically) we were in a context where the outer class has an associated 'this' reference, we would have to use OuterClassName.this"
I'm sort of confused by OuterClassName.this. It's counterintuitive because OuterClassName is a reference to a class, right?.
Ummm... depends what you mean. I'm assuming that there's an outer class, and its name is "OuterClassName". I could say "OuterClassName" is a "reference" to the outer class, in the sense that the name refers to the class. In ordinary human language I would call it a reference. But it's not a reference in the Java sense - it's not a bit of data in memory somewhere which points to an instance of a class. In this context "OuterClassName" is just a string which is part of a larger expression. The complete expression OuterClassName.this will be a reference - it will refer to a specific instance of the class OuterClassName, and it (the reference) can be passed around to other variables, methods, classes to tell other parts of the program what specific instance we're dealing with.
The syntax with the . is probably confusing. It looks similar to "obj.method()" or "obj.field". In both these cases, obj is a reference to an object of some class. But the dot is used in other contexts in which the thing to the left of the dot is not necessarily a reference. E.g. in "ClassName.staticMethodCall()", "ClassName" isn't a reference (in the Java sense), it's a qualifier which says "the static method staticMethodCall() is defined in class ClassName; look for it there". And in "OuterClassName.this" OuterClassName isn't a reference in the Java sense - it's a qualifier that says "the 'this' that I'm talking about is the associated instance of the class OuterClassName, not the associated instance of WhateverTheInnermostClassIs, as you would otherwise expect." (Bet you didn't think a dot could be so wordy, eh?)
The applicable JLS section is here.
value is referred from the enclosing instance of OuterC, but what I find odd is that the instance is the anonymous inner Runnable.
Yeah. In the original version there were two different variables named "value", and inside the printClassInfo() method the local variable took precedence. That is, when you said "value" it assumed that you meant the one that had just been defined in that method, rather than the one that had been defined further out in the outer class. But when you comment out the local variable, it turns out that the outer class instance variable was in scope and accessible - it was just ignored as long as there was a more local variable with the same name. The local variable is said to shadow the other variable.
In the first version of your code, if you want to refer to the "other" value from within method printClassInfo() (while it still has an unrelated local variable "value"), you have use a longer qualified name: "OuterC.this.value". Here "OuterC.this" is a reference to the OuterC instance (the one created with "new OuterC()") and ".value" accesses the field value for that instance.
Garrett Smith
Ranch Hand

Joined: Jun 27, 2002
Posts: 401
Jim, thank you for your help so far. This is helping me understand the language better and hopefully I will get a good score on scjp.
Now, I can't get the EnclosingClass.this to even compile. Can you tell me what I am doing wrong?

Why doesn't it compile?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I can't get the EnclosingClass.this to even compile
Your program isn't using EnclosingClass.this, it's trying to use EnclosingClass by itself (no .this afterwards) in a context that expects a reference to an instance. EnclosingClass is not a reference to an instance, it's just a class name, so the program doesn't compile.
Just replace
System.out.println("OuterD = "+OuterD);
with
System.out.println("OuterD.this = "+OuterD.this);
[ January 27, 2003: Message edited by: Jim Yingst ]
Garrett Smith
Ranch Hand

Joined: Jun 27, 2002
Posts: 401
Yes, you are right. Thank you very much.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: static inner classes