I want to know how many instances of a static member class can be created by the enclosing class. I assume one only, but then the following extract from Bloch doesn't make sense to me.
Quoting Joshua Bloch's Effective Java - Item 22*: Favor static member classes over nonstatic.
A common use of private static member classes is to represent components of the object represented by their enclosing class. For example, consider a Map instance, which associates keys with values. Many Map implementations have an internal Entry object for each key-value pair in the map. While each entry is associated with a map, the methods on an entry (getKey, getValue and setValue) do not need access to the map. Therefore, it would be wasteful to use a nonstatic member class to represent entries: a private static member class is best. If you accidentally omit the static modifier in the entry declaration, the map will still work, but each entry will contain a superfluous reference to the map, which wastes space and time.
He states that the map creates an Entry object for each key-value pair in the map, i.e. multiple instances of the static member class.
So my assumption is wrong! That means my understanding of static member classes is wrong. Everyone knows how a static member variable behaves, the classic static final string for instance - there is only one instance of the object.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API? Every other Collections class could then just provide it's own implementation.
[*] Just realised that it's item 18 in the PDF version of the book I have
That's because, it makes the package structure logically correct.
Now, this is a design discussion nobody would like to be dragged into.
Yes, you can have many instances of the nested class, no matter that the nested class is static.
When the nested class is static you can create instances of it without having an instance of the enclosing class, this is one of the benefits, and basically the main difference between static and non-static nested classes.
It's instantiated when it's constructor is called. Not any different from non-static classes. The nested class itself is loaded by the JVM, when the code first accesses it. Again this is not any different when compared to other classes, I think (not 100% sure of this though, but you can test it yourself). So I think you're kind of mixing the terms "loading the class by the JVM" and "instantiating the class".
As said, it's easier to create instances of static nested classes. You don't need an enclosing instance which is sometimes (maybe most of the times) exactly what you want.
See also:
(1) Nested Classes
(2) How can the JVM decide if a class is nested into another class?
(3) Loading of a nested class by the JVM
You can search for other references along these lines.
The reference (2) seems advanced and kind of peripheral to your question.
This is a common misinterpretation of the
static
keyword.When you use
static
with a variable it means there will be only one of these for all objects of this class or something like that.However, in the context of inner classes it means something completely different. A
static
inner class has no connection with an object of the enclosing class while a non-static inner class does.A
static
inner class:The
Map.Entry
class used by myTrieMap
class does not need to refer to the object that created it so it can be madestatic
to save the unnecessary reference.A non-
static
inner class:The
CharacterIterator
inside aStringWalker
object refers to the string to be iterated ass
which only exists once in theStringWalker
object. I can therefore create many iterators of aStringWalker
and they all walk the same string.Why this weirdness?
This seemingly illogical duality derives from the use of the
static
keyword inC
.In
C
you can (or at least used to be able to) do:and each time you called the function,
x
would be as you left it last time around - incremented in this case.The concept was that the
static
keyword indicated that the variable was scopefully enclosed by its enclosing block but semantically enclosed by its parent block. I.e. the above code was roughly equivalent to:but
x
was only allowed to be referenced inside the function.Take that concept forward into
Java
and things now make a little more sense. Astatic
inner class behaves exactly like it was declared outside the class while a non-static
inner bonds much more tightly to its enclosing instance - in fact it can refer to the instance directly.Also:
behaves much like
if it were legal.
Here endeth the lesson.
I think the Java team messed up the naming on this one. A static inner class (strictly speaking their correct name is "static nested class") is in no way different from an ordinary class except it has a fancy name (
Something.MyClass
instead ofMyClass
) and can be made private (i.e. not instantiable from other classes).In case of
Map
, it was solely chosen because the nameMap.Entry
makes it clear thatEntry
relates toMap
. As you suggest, it would have been perfectly reasonable to just use an ordinary class for this. The only difference is you don't get to writeMap.Entry
.I think what they should have done is to use the syntax for "non-static" inner classes (i.e. just
class
in an enclosing class) for static nested classes, and instead invent a new keyword to create "non-static" inner classes, because it's these that behave different from normal classes. Maybe something likeattached class
. AFAIK the keywordstatic
was chosen in order to avoid having too many reserved keywords, but I think it just encouraged confusion.