• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

static inner classes

 
Kev D'Arcy
Ranch Hand
Posts: 75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 ]
 
Kev D'Arcy
Ranch Hand
Posts: 75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Even if it's a static class?
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops, ok - there is always something new to learn... :roll:
Thanks for the pointer, Jim!
 
Garrett Smith
Ranch Hand
Posts: 401
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

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.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 401
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 401
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 401
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, you are right. Thank you very much.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic