wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Inner Classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Inner Classes" Watch "Inner Classes" New topic
Author

Inner Classes

E Weibust
Ranch Hand

Joined: Jun 13, 2003
Posts: 54
I came across these answers on a Whizlabs test. Can someone clarify what they are saying?
1. An instance of a top level nested class can be created without an instance of its enclosing class.
2. To create an instance of a non-static inner class, an instance of its enclosing class is required.
Thanks...


---<br />Erik Weibust<br /><a href="http://erik.weibust.net" target="_blank" rel="nofollow">http://erik.weibust.net</a>
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Check
this out. I'm sure it'll answer your questions and then some.


SCJP Tipline, etc.
Brian Joseph
Ranch Hand

Joined: May 16, 2003
Posts: 160
haha, that's great. Who draws all of those pictures? They're so cool.
FYI, this is the answer, in short.
1.
class Outer{static class Inner{}}
Outer.Inner obj = new Outer.Inner();
2.
class Outer{class Inner{}}
Outer.Inner obj = new Outer().new Inner();
[ June 25, 2003: Message edited by: Brian Joseph ]
Calvin Yan
Greenhorn

Joined: Jun 25, 2003
Posts: 19
right. cute pictures and remarks.
So inner classes could never be created without outter ones.


I will do the best with what God gave me!
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
So inner classes could never be created without outter ones.

Sad to say, you can declare a class in a static method. It is a local class. It is an inner class is a static context.
There is no outer object. You cannot reference instance variables and methods of the enclosing class.

Most people (including The Java Programming Language by Arnold, Gosling, Holmes) never talk about this case.
But if you see a local class or an anonymous class in the main method, well that is is an inner class in a static context. No enclosing instance. Outer.this is not defined.
[ June 27, 2003: Message edited by: Marlene Miller ]
Brian Joseph
Ranch Hand

Joined: May 16, 2003
Posts: 160
Since Local classes fall within the inner class category, sometimes I'd just prefer these there was more specific names for all these inner classes. Even after a few weeks of study I still get tripped up on the terms used to refer to the different types.
Like:
static member classes
non-static member classes
local classes
anonymous classes
And throw out 'inner class' when referring to any of these individually.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
I agree, Brian. "inner class" seems like a hodge-podge collection of heterogenous kinds of classes. You cannot even say - as some people do - that they all have an enclosing instance.
When I organize the classes in my mind, I do not include the idea of inner classes. Classes are either top-level or nested. Nested classes are member or non-member. Members are static or non-static. Non-members are local or anonymous. THEN I draw a loop around those that are inner classes (non-static member, local and anonymous).
A few times I scanned the JLS to see exactly what the purpose of the words inner class is. What rules apply to and only to all inner classes? Well, I forget what I found, but whatever it was, it was not very useful to me.
[ June 27, 2003: Message edited by: Marlene Miller ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
From the original post:
1. An instance of a top level nested class can be created without an instance of its enclosing class.
Note that Java hasn't officially had any "top-level nested classes" since the release of JLS 2nd ed in 2000. They jettisoned that confusing term in favor of the much more logical "static member class". But many books and sample tests continue to perpetuate the old usage. Just ignore them; hopefully they'll die eventually.
2. To create an instance of a non-static inner class, an instance of its enclosing class is required.
As Marlene points out, this just isn't true. Ignore it.
I agree, Brian. "inner class" seems like a hodge-podge collection of heterogenous kinds of classes.
I agree. It's rarely useful to know whether a class is "inner" or not. It's useful to know if it's a member or not, and whether it's either [static or from a static context] or [not remotely static]. But none of these concepts directly maps to "inner". Very annoying; too bad JLS2 didn't revise this terminology as well.
For the exam: I'm pretty sure that the modern programmer's exam does not ever depend on knowing that a local class in a static context is still considered an inner class. You probably won't even see the term "inner class" at all - they'll just show some code and make you figure out what it can do, or whether it's legal or not. Similarly you shouldn't need to worry about terms like "static inner class" or "top-level nested class" because they've removed the old questions that used this icky terminology. If you do take the exam and see either of these terms, be sure to remember the question as well as you can, and write a nasty letter to Sun about it. Well, a polite nasty letter.


"I'm not back." - Bill Harding, Twister
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Here is one thing that applies to all inner classes - Inner classes may not declare static members, unless they are compile-time constant fields. Also, inner classes may not declare static initializers or member interfaces.
(I wish someone could explain why inner classes cannot declare static members.)
[ June 27, 2003: Message edited by: Marlene Miller ]
Alton Hernandez
Ranch Hand

Joined: May 30, 2003
Posts: 443
Originally posted by Marlene Miller:

(I wish someone could explain why inner classes cannot declare static members.)
[ June 27, 2003: Message edited by: Marlene Miller ]

Also add to that is why they can inherit static members even though they themselves cannot declare static memebers.
Seems to me that there's contradiction there.
[ June 27, 2003: Message edited by: Alton Hernandez ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
OK, this is another of those things most SCJP students don't really need to know, but it is directly related to things you [i]do need to know, so I'll answer here. For the exam you don't need to know the why, you just need to know the rules. But knowing why may be nice for your own sanity. For those who want to keep things simple, just ekip this post.
[MM]: I wish someone could explain why inner classes cannot declare static members
[AH]: Also add to that is why they can inherit static members even though they themselves cannot declare static memebers.

Yes, these two facts are rather strange, especially when considered together. This question has come up before, but this is the first time I [believe that] I have come up with a good detailed explanation. See if you agree. I believe that while it might have been possible for the JLS rules to allow inner classes to have static members, they are not really necessary, and would often cause confusion, so they were banned in a (belated) attempt to keep the language simple. Or at least, not quite as complex as it could have been. :roll: Consider:

Should this compile? What should it do? Right now, it won't compile, because innerStaticField is, well, a static field declared in an inner class, which is not allowed. If this were allowed, then what? One possibility is that the output should be:

However, there's a problem. The field innerStaticField is a final static field, yet it is showing up with three different values here. This makes sense if you consider that the definition of Inner is only in scope inside the method foo(), and when the method exits, everything about Inner may be forgotten, and when foo() executes again it creates a new Inner class which can have a different static field. Well, maybe. But I think a lot of people would be confused by this, and would expect that there should be only one value for a final static field, period, rather than three. But how should this be enforced? Should we disallow "final" as a modifier for a static field in an inner class? That won't really help - the problems here are not because of final; I just added that to make the problem more obvious. The real problem is that by the end of the main() method, there is a List with 9 objects containing 3 different values of a static field. Simultaneously. This is going to confuse people; it's going to be hard to explain that "static" in this context is limited in scope to the duration of a single execution of the foo() method, and a subsequent execution creates a different "static" variable. Ugh.
Ultimately, it seems easier to just say you can't declare a static field in an inner class. If you want a bit of data which is scoped to the method foo(), then declare it as a (final) local variable in the outer class method foo(). Or maybe you want it scoped to an instance of the outer class instead (a non-issue here since I declared my inner class in a static method). If so, make the variable an instance variable in the outer class. Or for a "truly" static variable, make it a static variable in the outer class. Fundamentally, there's no reason it needs to be declared in the inner class; it will just cause confusion there.
Note that through all this example there's been a Base class with its own static field, inherited by Inner. Forturnately, there's no way for this inherited field to cause the same type of confusion. I can always look at where it was originally declared, as a final static field of a top-level class, and determine that there's only one value that field can ever have in the life of the JVM. (Well, ignoring some weird effects with blank final fields before an initializer is completed.) Even if the field is inherited in an inner class, its original declaration is nice and unambiguous, and it just doesn't cause the problems that it would have if it were declared inside an inner class.
Hope that helps...
[ June 29, 2003: Message edited by: Jim Yingst ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Oh dear, out of scope again.
Jim, you have presented a very convincing example and explanation. And complete � addressing both rules. I have no questions.
Inner member classes differ from local classes not only by where they are declared. Inner member classes cannot be instantiated from a static context.

: non-static variable this cannot be referenced from a static context,
Object o1 = new Inner();
Perhaps inner member classes could have static fields?
Thank you very much for your ideas and your time.
Bene facis. Gratias tibi ago. Marlene
Alton Hernandez
Ranch Hand

Joined: May 30, 2003
Posts: 443


[MM]:Inner member classes differ from local classes not only by where they are declared. Inner member classes cannot be instantiated from a static context.
[JY]:This is going to confuse people; it's going to be hard to explain that "static" in this context is limited in scope to the duration of a single execution of the foo() method, and a subsequent execution creates a different "static" variable. Ugh.

Jim, thank you for that explanation.
I have 2 sample programs here(modified from yours) which would confuse a lot of people, including myself. It seems to show how inconsistent the behaviour of an inherited static member is when used inside an inner class.
Test has an non-static inner class while Test2 has a local class. Both inherit a static member baseStaticField from class Base.
As you can see from the output, the local class Test2 has 9 objects containing different values of the static field baseStaticField. But if you were to compare that with the non-static inner class Test, the value of the static field is a consistent C - the last value assigned to the static field.


In my opinion, program Test behaves in accordance with the definition of static.
But whatever the reason why these 2 programs behaves differently, inheriting and defining a static member should not be any different. They both end up as members of the subclass.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[MM]: Perhaps inner member classes could have static fields?
Perhaps, but I think these would be subject to similar problems and confusions. Consider two InnerMember instances which were associated with two different instances of an Outer class. If Inner had a static field, should it have just one value for all Inner instances, or just for Inner instances associated with the same Outer instance? I would favor the latter, but again it would not be obvious, and again that static field of Inner could just be made a static or nonstatic field of Outer instead.
[AH]: As you can see from the output, the local class Test2 has 9 objects containing different values of the static field baseStaticField.
It looks that way - but:

Your toString() is changing the value of the static field just before it's printed. That's just evil. So what's happening is that at any instant, all 9 objects would see the same value of baseStaticField, as you'd expect. But every time toString() is invoked on a different instance, that can change baseStaticField (for all instances). So you've really got one variable that you keep changing.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Thank you again, Jim.
Whenever I have tried to figure out why inner classes cannot have static members, I have always assumed, without realizing I was assuming, that there is only one set of class data.
Without that assumption, and even more, by preferring there be multiple sets of class data � one set per method invocation or one set per objects belonging to a single enclosing instance � you have found the crux of the problem.
That is the most important thing I have learned from you.
[ June 30, 2003: Message edited by: Marlene Miller ]
Alton Hernandez
Ranch Hand

Joined: May 30, 2003
Posts: 443
Originally posted by Jim Yingst:

Your toString() is changing the value of the static field just before it's printed. That's just evil.

Oops, made a mistake there. Pasted at the wrong location. It should had been inside the the constructor, above toString().
But anyway, you are right, the value is consistent.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
This is a footnote to the discussion on why inner classes cannot have static members.

From the Assertion Specification,
The compiler adds a synthetic field to every class that contains one or more assert statements. The synthetic field contains the complement of the actual assertion status of the class:
static final boolean $assertionsDisabled =
!<EnclosingTopLevelClassName>.class.desiredAssertionStatus();
This declaration must be placed before all other static variable declarations and static initializers in the class. The name of the field is not part of the specification: it is local to the class and can vary from implementation to implementation and class to class. This field may occur in contexts where static fields are not permitted by the Java programming language, such as inner classes; because it is a synthetic field, this does not present a problem. While the presence of such a field violates the JLS, it does not violate the JVMS.

So the compiler adds a synthetic static field to inner classes. Well, well, well.
 
wood burning stoves
 
subject: Inner Classes
 
Similar Threads
Inner class mult choice
Inner classes; when should they be static vs. instance?
Where Can I Read about Non-Static Inner Classes?
nested inner classes
Inner Class Question