Properly, the term inner classes only applies to the fourth, fifth and sixth types. For the remainder of this essay, I will attempt to use the term inner class only in that sense.
Just to make matters even more confusing, many programmers refer to both static nested classes and inner instance classes as inner classes, even though properly speaking inner implies non-static i.e. instance. I tend to use the term nested only for static nested classes, which is not quite kosher either.
The word static is so badly abused in Java. It has so many meanings, none of them anything like its meaning in ordinary English. The term static class is especially misleading. Static classes can be instantiated just like any other. They have both static and instance fields. They were probably called static just to avoid creating another reserved keyword.
Inner classes have no keyword to mark them, other than class. Anonymous inner classes don’t even have that. What makes them nested is the way the {} marking the beginning and end of the class nest with other classes.
static nested classes have the marking static class.You can define an anonymous class, create an anonymous instance of it and pass it as a parameter to some method all in one (albeit very long) line. Anonymous classes were originally intended primarily for use by code generators. If you want to write really hard to follow code, you can nest inner classes within inner classes and make them anonymous if you
Here
// instantiating an inner class from inside the outer class. Inner in = new Inner(); // instantiating an inner class from outside the outer class. Outer out = new Outer(); Outer.Inner in = out.new Inner();
You can instantiate an static nested class like this:
Allowed Scopes for Various classes | ||
---|---|---|
Type of Class | Possible scopes | Notes |
top level classes | public default | At most one top level class per *.java file can be public. Note that top level classes cannot be private (since which class would they be private to?). Further, they cannot be protected. Why I don’t know. |
static classes | public protected default private | default refers to the package level scope you get by leaving off a scope modifier. |
inner classes | public protected default private | Note that inner classes are not necessarily private. Unless you make an inner class private it is also known outside the outer class. |
anonymous classes | none | Such classes are have no name, hence have no scope. They are known thus only within the statement in which they are defined. |
local classes | none | Such classes are known only within the method/block in which they are defined. |
Nested Class Inheritance Rules | |||||
---|---|---|---|---|---|
Subclass | |||||
Superclass | top level class | nested static class | inner class | anonymous inner class | local inner class |
top level class | |||||
nested static class in same outer class |
|||||
nested static class in different outer class |
|||||
inner class in same outer class |
|||||
inner class in different outer class |
|||||
anonymous inner class | |||||
local inner class |
You might imagine that inner classes are merely a scope mechanism, that they are independent classes, visible only to the outer class. Not so. For every inner class object there must exist an associated outer class object. You can’t create inner class objects without first creating an outer class object. You must create inner class objects in instance methods so that this implicitly gives you the corresponding outer class object.
On the other hand, if you declare the nested class static, that class can be independently instantiated. Since the class is not associated with any particular instance of the outer class, you may not use MyOuterClass. this.myOuterInstanceMethod() to access its instance methods. You could use someInstance. myOuterInstanceMethod() though and, of course, you can access the outer class’s static methods with myOuterStaticMethod() or MyOuterClass. myOuterStaticMethod()
If you are an assembler programmer, the following explanation may be helpful. If not, please ignore the rest of this paragraph. It will just confuse you. Inner class constructors get passed a hidden parameter, a reference to the outer class object that created them. static nested classes don’t have this hidden parameter. This is analogous to the way instance methods have hidden this parameter, where static methods do not.
The reverse rules for how outer classes get at the field and methods of nested ones are obvious. Outer classes access inner class and nested class fields and methods the same way they would any other independent class.
The local variables that must be final in order to be accessed, live in the method that instantiates and encloses the anonymous class. The access we are talking about is direct use of the variable names from inside the methods of the anonymous class.
Again, let
The rule is anonymous inner classes may only access final local variables of the enclosing method. Why? Because the inner class’s methods may be invoked later, long after the method that spawned it has terminated, e.g. by an AWT (Advanced Windowing Toolkit) event. The local variables are long gone. The anonymous class then must work with flash frozen copies of just the ones it needs squirreled away covertly by the compiler in the anonymous inner class object.You might ask, why do the local variables have to be final? Could not the compiler just as well take a copy of non-final local variables, much the way it does for a non-final parameters? If it did so, you would have two copies of the variable. Each could change independently, much like caller and callee’s copy of a parameter, however, you would use the same syntax to access either copy. This would be confusing. So Sun insisted the local be final. This makes irrelevant that there are actually two copies of it.
The ability for an anonymous class to access the caller’s final local variables is really just syntactic sugar for automatically passing in some local variables as extra constructor parameters. The whole thing smells to me of diluted eau de kludge.
static methods in an anonymous class could not be called from outside the anyonymous class, which perhaps explains part of it.
Mark Space offers this explanation for the restriction. Conceptually, non-static member classes, local and anonymous classes are all a part of the enclosing class. Thus they should be using the enclosing class for any static members.
For future potential optimization, preventing static members might allow future JVMs (Java Virtual Machines) to take some short cuts with inner class objects and initialize the objects more quickly or otherwise do away with one or more steps involved in creating their class object. Since static members weren’t needed (since they could be promoted to an enclosing class (however, not enclosing object)), they were proscribed.
This page is posted |
http://mindprod.com/jgloss/nestedclasses.html | |
Optional Replicator mirror
|
J:\mindprod\jgloss\nestedclasses.html | |
Please read the feedback from other visitors,
or send your own feedback about the site. Contact Roedy. Please feel free to link to this page without explicit permission. | ||
Canadian
Mind
Products
IP:[65.110.21.43] Your face IP:[3.142.119.49] |
| |
Feedback |
You are visitor number | |