Win a copy of Mastering Corda: Blockchain for Java Developers this week in the Cloud/Virtualization forum!
  • 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Bear Bibeault
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Jj Roberts
  • Carey Brown
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

When is an anonymous inner class NOT an inner class? Always?

 
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey there!
I have some questions about inner classes, and I hope I don't spark a riot here. There seems to be a whole lot of confusion regarding so called "static inner classes" that are officially called "top level-nested classes" and are therefore not officially inner classes. The term "top level- nested class" seems to be pretty undescriptive term to me, and your normal inner class seems to also fit into that description as well, i.e.- it is more top level than the "static inner classes" and it is also a nested class. I think (if I am understanding this correctly, a lot of confusion results from this unfortunate term. Personally, I prefer the term "method classes" or "local classes" since it emphasizes that such classes can only exist within a method. Anyway, enough rambling - here are my questions.
1) Why exactly CAN'T a NON-static inner class have Static members? What is the essential feature about these classes that prevent it from possessing variables that are accessed at the class level rether than the object level?
2) Can Non-static inner classes access Static fields of the enclosing class? If not, WHY not?
2) One book I was reading said that Anonymous inner classes can only be contained within a METHOD of an inner class. But if this is true then I conclude that ALL Anonymous inner classes are in fact officially NOT inner classes, but are "top level nested classes". Still with me? The book goes on to say that Anonymous inner classes can only exist in a method BECAUSE such a class is INSTANTIATED AND DECLARED on the same line. But this doesn't seem to be a compelling explanation to me. Why can't such a class can't be INSTANTIATED AND DECLARED outside of any method. What is wrong with the following code?
class Fruit
{
String Taste;
}
class Orange
{
Fruit f=new Fruit(){/* Class Body defined here */};
}
Here I have created an Anonymous Inner Class (which in this case is NOT a top-level nested class, and thus REALLY is an inner class) that extends Fruit. This Anonymous Inner Class is not contained within ANY method, and seems syntactically correct to me. The variable f will now contain a reference to the instance of the Anonymous Inner Class that extends Fruit. Am I missing something here, or is the book incorrect?
Okay ... my head is starting to spin now ... I guess I should go.
Thanks in advance

Dan
 
"The Hood"
Posts: 8521
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Communication is a difficult thing at best. Sun has chosen to use the word "inner" to mean any class that cannot exist without an instance of the outer class. Since that does not apply to static nested classes, by definition they are not inner classes.
Now the fact that alot of folks chose to interpret the word "inner" to mean "defined inside another class" is NOT Suns problem. It just means that we need to get our definitions in line.
Now for 1) In order to have static members it is necessary for them to be accessed without any instance of the class created.
Consider what the syntax would need to be.
OuterClass.InnerClass.staticField
What you have just described is essentially a static field of the OUTER class. By definition Inner means "cannot exist without an instance of the outer class" and this violates that definition.
2) Yes Inner classes can get at the static stuff of the enclosing class. They may also inherit static stuff if they sub-class something (hopefully other than the enclosing class).
2 again) Anonymous classes are declared as the parameter to a method of the Outer class. You can not use the method without an instance or member of the Outer class. That makes them inner classes.
What you have created in your example is syntax that is not supported in Java so is not an inner class OR an anonymous class.
 
Dan Temple
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why thank you kindly Barkeep!
Allow me to buy you a drink for your help. Your description of an inner class as "any class that cannot exist without an instance of the outer class" sure makes things easier. But I fear that too much dust on the trail has muddled this poor cowboy's head on a few things you said.
Are you saying that an inner class cannot have static fields because a static field MUST be accessible without an instance of an object? I see how this is a contradiction, but I don't see why this should be the ESSENTIAL definition of a static field. I thought that the ESSENTIAL characteristic of a static member was that it existed at the class level, rather than the object level, and how exactly it was accessed was irrelevant to its status as a STATIC member. After all one CAN access a static member using the syntax 'object.static_member', even though it is considered bad form. But if the essential definition of a static field is what you say it is, then that is that. I guess my beef would be concerning that unsatisfactory feeling over the definition. But then if that is the definition, why allow an Inner Class to have Static Final Fields but no Static Fields? Like Static fields, shouldn't Static final fields be essentially accessible without an instance?
Okay, I see what you are saying concerning Anonymous Classes always being part of a member method and therefore being true inner classes. But I guess my question is WHY should this be? What essential property of Anonymous Classes have I violated in my Fruit/Orange example? If it is a brute fact about the Java language, then so be it - but I must admit that brute facts have always left me somewhat unsatisfied.
Now at the risk of kicking over a hornet's nest with these cowboy boots, if an inner class is defined as one that cannot exist without an instance of the outer class, then a "top-level nested class" declared within a member method IS by definition an inner class, and all this fuss about "top-level nested classes" NOT being a true inner class is just confusion. Is this correct?
Thanks
Hatman Dan
 
Dan Temple
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Whoops!
Sorry ... I just realized I confused a "Top-Level Nested Class" with a "Method" or "Local Inner Class" (A class that must be defined within a method of an outer class). So please ignore my remarks in the final paragraph. Looks like I was the only one that got stung by those hornets. The rest of the reply still stands ... at least I think it does ...
Dan
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sun has chosen to use the word "inner" to mean any class that cannot exist without an instance of the outer class.


Well, that was probably the intent. But it's not quite true - you can have an inner class in a static context, which means for example a local class defined inside a static method. Such a class has no enclosing instance, but is still termed an inner class, because the official definition of "inner class" is a nested class that is not static. ("Defined in a static context" is technically not the same as actually being static, though they probably should have made them equivalent.)

Now the fact that alot of folks chose to interpret the word "inner" to mean "defined inside another class" is NOT Suns problem.


Well, it would have helped if the document that originally defined nested classes (both static and inner) hadn't been titled "Inner Classes Specification". I got the feeling not everyone in Sun was on the same wavelength there; there were a few inconsistencies in that document. But the JLS2 seems to iron it all out.
Why can't inner classes declare static members? It's not that it's impossible to access them - inner classes can inherit static members, and the inherited members are accessible normally. But it's conceptually confusing - consider:
<code><pre>
Outer o1 = new Outer();
Outer o2 = new Outer();
Outer.Inner i1a = o1.new Inner();
Outer.Inner i1b = o1.new Inner();
Outer.Inner i2 = o2.new Inner();
i1a.staticMember = "1a";
i1b.staticMember = "1b";
i2.staticMember = "2";
</pre></code>
Did the last two lines of code refer to the same member, or different ones? Certainly i1a and i1b referred to the same member, but what about i2? To me the "natural" interpretation would be that a static variable of an inner class (outside a static context) should still be associated with its enclosing iinstance. But not everyone would agree, I'm sure. To eliminate this unnecessary confusion, static members of inner classes are disallowed. If you want a variable which occurs once for the whole outer class, declare it a static member of the outer class. If you want one associated with each outer instance but not each inner, then declare it a nonstatic member of the outer class. And if you want one variable per instance of the inner class, declare it a nonstatic member of the inner class. What else would you need?
 
Cindy Glass
"The Hood"
Posts: 8521
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, Jim's right, that's why I tweaked my definition in the answer to 2 again) to be "You can not use the method without an instance or member of the Outer class".
Should have tweaked in both places.
 
Cindy Glass
"The Hood"
Posts: 8521
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe they should have called them "dependant classes" instead of inner classes?
 
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Folks,
Hi. I joined this discussion kind of late, but I'd like to try to clear up a few things. The terminology for describing nested classes was not well-specified until the second edition of the JLS came out last year. Unfortunately, the waters were more than a bit murky prior to that. Gilad Bracha is the man who deserves the credit for tightening up the spec.
In Item 18 of my book ("Favor static member classes over nonstatic"), I describe the new terminology, and tell you when to use which kind of nested class. I'll briefly summarize a few of the more important points here.
A nested class is a class defined within another class. A non-nested class is known as a top-level class. (There is no such thing as a "top level-nested classes.") There are four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes.
Here are simple examples:
<code>
class A {
// static member class
static class B { ... };
// nonstatic member class
static class C { ... };
static void foo {
// anonymous class
D d = new D() { ... };
// local class
class E { ... }
}
}
</code>
All nested classes but the first kind (static member classes) are known as inner classes. Note that it is not the case that inner classes always have enclosing instances: anonymous classes and local classes have enclosing instances only if they occur in a non-static context. In the example above, D and E are inner classes but they do not have enclosing instances, as foo is a static method of A. Don't feel bad if you didn't know this: it wasn't codified until recently, and it contradicts prior common usage. Unfortunately, there is no single term describing a nested class that does have an enclosing instance.
To answer a few of your specific questions:
1) Why exactly CAN'T a NON-static inner class have Static members? What is the essential feature about these classes that prevent it from possessing variables that are accessed at the class level rather than the object level?
This is largely a philosophical issue. The designers of the nested class facility felt that such fields belonged in an enclosing non-inner class.
2) Can Non-static inner classes access Static fields of the enclosing class?
By non-static inner classes, I assume you mean inner classes with enclosing instances? At any rate, the answer is yes: all nested classes can access static fields of enclosing classes.
2) One book I was reading said that Anonymous inner classes can only be contained within a METHOD of an inner class. But if this is true then I conclude that ALL Anonymous inner classes are in fact officially NOT inner classes, but are "top level nested classes". Still with me? The book goes on to say that Anonymous inner classes can only exist in a method BECAUSE such a class is INSTANTIATED AND DECLARED on the same line. But this doesn't seem to be a compelling explanation to me. Why can't such a class can't be INSTANTIATED AND DECLARED outside of any method. What is wrong with the following code?
I'm afraid that I don't follow this, but the book you were reading would appear to be in error. It is not uncommon for anonymous classes to occur outside of methods, in static field initializers:
<pre>
public class Foo {
public Comparator WEIRD_ORDER = new Comparator { ... };
...
}
</pre>
I hope this clears things up a bit. I know that it's a pretty dense
subject. I go into a lot more detail in Item 18 of my book.

------------------
Joshua Bloch
Author of Effective Java
[This message has been edited by Joshua Bloch (edited July 11, 2001).]
 
Joshua Bloch
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is way off topic but - aargh! - does anyone know how to format code examples on Java Ranch? When I use the pre tag, I lose vertical whitespace. When I use the code tag, I lose horizontal leading whitespace (i.e. indentation). Either way, the code looks yucky.

[This message has been edited by Joshua Bloch (edited July 11, 2001).]
 
Ranch Hand
Posts: 1492
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Joshua,
Just use the [ CODE ] and [ /CODE ] tags and your code will look indented correctly (remove the spaces when you type it!). You will however lose vertical spaces. IMO, empty lines are overrated anyway!
Regards,
Manfred.
[This message has been edited by Manfred Leonhardt (edited July 11, 2001).]
 
Cindy Glass
"The Hood"
Posts: 8521
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can use the [ code ] and [ /code ] tags without the spaces, but the font is tiny.
Sometimes I do
[ code]< font size=2.5 >
< /font> [ /code]
 
Dan Temple
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks to everyone that responded. Believe it or not, my Vertigo seems to have cleared up.
Jim: If I understand you correctly, there is nothing PER SE wrong with an inner class having static fields, at least theoretically. The problem stems from the ambiguity with whether inner objects that possess different enclosing objects refer to the same field or not. So to eliminate this ambiguity static fields are a no go for inner classes. Consequently, this also explains why static final fields are legitimate for inner classes, since by virtue of being FINAL, the ambiguity is made moot. Right?
Joshua: Thanks for your clarification on the various species of inner classes. That certainly helps. But are you saying that static inner classes are not officially called by SUN as �top-level nested classes�? By officially, I mean as far as Java 2 certification is concerned. I got the technical terminology from this site�s WONDERFUL campfire story �Getting in touch with your inner class�. Anyone have any thoughts on this? Also thank you for your input on anonymous classes. I was tired of banging my head against the wall as to why anonymous classes could not exist outside of any method.
Dan
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Josh- to avoid losing vertical whitespace, put at least one space on each empty line. Otherwise our UBB software eats the line for some reason inside [code] or <pre> tags.
FYI, you can look at what tags other people used in their posts by clicking on the "Edit" icon for that post. You won't be allowed to submit actual changes to other people's posts (unless of course you want to become a bartender here ), but this is a good way to get a look at the "source" for what you see displayed. Or a close approximation - UBB also does some substitutions for some characters, so what you see with Edit may not be exactly what was typed originally, but in most cases its close enough to figure out what they were doing.
 
Ranch Hand
Posts: 81
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Originally posted by Cindy Glass:

Sometimes I do
[ code]< font size=2.5 >
< /font> [ /code]


I always wondered how you made your code font larger. Thanks Cindy!
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dan- yes, that's my thinking anyway. I may be missing something however. Also, it's not quite enough that a static field be final in order to declare it in an inner class - it must also be definitely initialized with a compile-time constant before the class declaration. Otherwise it's still not certain what value it might have.
Regarding "top-level nested classes" - that's the old term, from the Inner Classes Specification. Plenty of books and tutorials still use it - but Sun has dropped it as of the JLS2, which is a Good Thing in the long run, I think. I guess we should update the campfire story.
 
Joshua Bloch
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Originally posted by Dan Temple:
Joshua: Thanks for your clarification on the various species of inner classes. That certainly helps. But are you saying that static inner classes are not officially called by SUN as �top-level nested classes�? By officially, I mean as far as Java 2 certification is concerned.
[/B]


I would hope so. The official Java language specification is (not surprisingly) The Java Language Specification (2/E), by Gosling, Joy, Steele and Bracha I would assume that the people who develop the certification exam use this as their reference. If not, you'd certainly have grounds for complaint. This reference is duly approved by the Java Community Process, so there's no question that it's authoritative.

I got the technical terminology from this site�s WONDERFUL campfire story �Getting in touch with your inner class�. Anyone have any thoughts on this?


I agree that it's a WONDERFUL piece. I've never seen anything quite like it. That said, it should be updated to conform to the JLS 2/E terminology. (My apologies if this has already been done; I read it a while back.)

------------------
Joshua Bloch
Author of Effective Java
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The only catch is, the JLS2 was not out yet back when the SCJP2 was exam was originally developed. I believe they have updated it since then, but I don't know how thorough this has been. Hopefully the exam simply avoids testing people on the terminology in this case, instead focusing on code examples to see if people understand how it works. But I may be overly optimistic. The original SCJP2 exam apparently did have one question regarding a "static inner class", which was never part of the official terminology.
 
Hold that thought. Tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic