Static inner classes

V

VisionSet

Jamin said:
Anyone have a good example why one would use a static inner class?

[New to actually implementing them myself, so very interested in this
discussion. Though I believe they are widely used in GUI, something I've
done very little of.]

Anywhere you want one instance of another class associated solely with one
particular class, in the same way you have a static class attribute, you can
have a static class class.

Encapsulating creation of the outer class. A factory inner class
responsible for registering itself with a central factory (abstract super
class).
Very OTT most of the time but if you want complex dynamic creation...

ie

class Outer implements MyInterface {
static {AbstractFactory.addFactory(new Factory());}
static class Factory extends AbstractFactory {
MyInterface createInstance() {return new Outer();}
}
}

Or do you mean - 'why would you want an innerclass that can't see the
outerclasses attributes?'
Closely ties one class with another, where it doesn't make any sense for it
to be elsewhere.
 
J

John C. Bollinger

Jamin said:
Anyone have a good example why one would use a static inner class?

Terminology first: if it's static then it isn't an inner class. (It's a
"static nested class".) Inner class instances have associated instances
of all lexically enclosing classes, up to the innermost top-level class.
Static nested classes and classes that are package members are
top-level classes.

Static nested classes give you two main benefits:
(1) Name scoping
(2) access control

Name scoping is potentially useful when one class is so tightly related
to another that you want to make the relationship explicit in its name.
A highly visible example from the platform API would be
java.util.Map.Entry.

Access control means that a static nested class can be declared
protected or private for more precise encapsulation. If methods of a
static nested class messed with static fields of an enclosing class then
this might become important; otherwise it's really just question of
design preferrences as far as I can see.

In most cases I don't find either of these especially persuasive, but
there have been one or two occasions when I have chosen the static
nested class approach.


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

John said:
Static nested classes give you two main benefits:
(1) Name scoping
(2) access control

Oh, and also (very importantly):

(3) Static nested classes can access private members of their enclosing
classes.

I actually thought of a practical use for the construct along those
lines: the nested class is a Comparator implementation for instances of
the enclosing class, and it bases its comparison on private state of the
enclosing class. Instances of the nested class should not be associated
with any one instance of the enclosing class, but must be able to access
the private state of enclosing class instances. A static nested class
is a natural fit there, and indeed the only solution I can think of that
doesn't require tricks with reflection.


John Bollinger
(e-mail address removed)
 
S

secret

If it's a "static" nested class, how can it access any members (private or
otherwise) of an instance of the enclosing class? And you refer to
"instances of the nested class" which also implies it's not static.

alan
 
T

Tor Iver Wilhelmsen

John C. Bollinger said:
(3) Static nested classes can access private members of their
enclosing classes.

More precisely: The compiler synthesizes accessors for private members
used by nested classes.
 
V

VisionSet

(3) Static nested classes can access private members of their enclosing
classes.

I, like alan, am mystified by this.
It does work, but why and what is the justification?
 
B

Bent C Dalager

I, like alan, am mystified by this.
It does work, but why and what is the justification?

Consistency I suppose.

Any part of a given class C has access to the private fields of that
class C. A nested class C.A is part of the class within which it is
nested (class C) and so gets this level of access to its outer class.

Static methods also have access to the private fields of its class.
Why shouldn't static nested classes have it?

In other words, if this is legal:
public class Test
{
private int a;

public static void main(String[] args)
{
Test test = new Test();
test.a = 3;
System.out.println("a is " + test.a);
}
}

then it makes sense that this is also legal:
public class Test
{
private int a;

static class Inner
{
public void wowMe()
{
Test test = new Test();
test.a = 3;
System.out.println("a is " + test.a);
}
}

public static void main(String[] args)
{
Test.Inner inner = new Test.Inner();
inner.wowMe();
}
}

Cheers
Bent D
 
V

VisionSet

Bent C Dalager said:
I, like alan, am mystified by this.
It does work, but why and what is the justification?

Consistency I suppose.

Any part of a given class C has access to the private fields of that
class C. A nested class C.A is part of the class within which it is
nested (class C) and so gets this level of access to its outer class.

Static methods also have access to the private fields of its class.
Why shouldn't static nested classes have it?

public class Test
{
private int a;

static class Inner
{
public void wowMe()
{
Test test = new Test();
test.a = 3;
System.out.println("a is " + test.a);
}
}

public static void main(String[] args)
{
Test.Inner inner = new Test.Inner();
inner.wowMe();
}
}

That is not what I meant:

test.a = 3; // via an object

I meant:

a = 3; // direct, which you could do if it was not static.

My mistake when I compiled a quick test - code in wrong place - it works as
I expect.

Thankyou
 
M

Michael Borgwardt

secret said:
If it's a "static" nested class, how can it access any members (private or
otherwise) of an instance of the enclosing class?

If the members are static temselves, otherwise through an instance it's given
(e.g. as a method parameter).
And you refer to
"instances of the nested class" which also implies it's not static.

Um... no. With a nested class, the "static" keyword does NOT mean that
there can be no instances, it just means that instances of it are not
implicitly linked to an instance of the enclosing class as is the case
with non-static nested classes.
 
J

John C. Bollinger

If the members are static temselves, otherwise through an instance it's
given
(e.g. as a method parameter).

Right, which is exactly what would happen in a Comparator
implementation. (Instances of the enclosing class provided to an
instance of the static nested class.) It seems to me a very nice and
tidy example of how a static nested class could be useful.


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

Tor said:
More precisely: The compiler synthesizes accessors for private members
used by nested classes.

No, as far as I can tell synthetic accessors are an implementation
choice, not a requirement specified by the language. It is possible
that this is the only viable implementation given the current JVM
specifications, but I don't think it is correct to describe it as a
general property of static nested classes.


John Bollinger
(e-mail address removed)
 
T

Tor Iver Wilhelmsen

John C. Bollinger said:
No, as far as I can tell synthetic accessors are an implementation
choice, not a requirement specified by the language. It is possible
that this is the only viable implementation given the current JVM
specifications, but I don't think it is correct to describe it as a
general property of static nested classes.

Until class verification changes, it is. A different class cannot
access another class' private members as long as JVM spec § 5.4.4 is
worded the way it is and the checks done in pass 4 of class
verification are as they are.
 
J

John C. Bollinger

Tor said:
Until class verification changes, it is. A different class cannot
access another class' private members as long as JVM spec § 5.4.4 is
worded the way it is and the checks done in pass 4 of class
verification are as they are.

It seems we will have to agree to disagree.

<opinion whose="mine">
Reference to the JVM spec is not relevant. That directs how the
language feature can be implemented, not what the language feature _is_.
The JLS (plus associated corrections, addenda, etc.) defines the
language, and I have found no reference to synthetic accessors there.
It is a nontrivial distinction, essentially between interface and
implementation, that in this case is bridged by java compilers.
</opinion>


Regards,

John Bollinger
(e-mail address removed)
 
C

Chris Uppal

John said:
<opinion whose="mine">
Reference to the JVM spec is not relevant. That directs how the
language feature can be implemented, not what the language feature _is_.
The JLS (plus associated corrections, addenda, etc.) defines the
language, and I have found no reference to synthetic accessors there.
It is a nontrivial distinction, essentially between interface and
implementation, that in this case is bridged by java compilers.
</opinion>

While I agree with your position in principle, the pragmatic reality is that
most Java is intended to run on a JVM. That leads to a reflection:

It's becoming increasingly clear to me that there's something of a division
developing between the programmers who think in terms of Java-the-language, and
for whom the JVM is an implementation detail. And those who think of
Java-the-platform, for whom the JVM is central, and Java-the-language is just
one way of creating classfiles for running on that platform.

That wouldn't cause a problem, except that the features of Java-the-language
are
diverging increasingly from those of Java-the-platform. Static inner classes'
access to private variables is a case-in-point. For a Java-the-language man
(as you appear to be, judging only by your <option/> above) the synthetic
accessors are an implementation detail, at the discretion of the compiler. You
(as a competent programmer) will undoubtedly know that they are generated, and
may -- in some circumstances -- consider the effects they have, on security for
instance.

For a Java-the-platform man, such as myself, the position is rather different.
I work mostly at the bytecode/JNI level, so I'm probably more JVM-oriented than
most, but for me the ability of a static nested class to access private
variables of its enclosing class is a complete myth. As is the "nested" class
itself. The unreality of such constructs, and the reality of synthetic
accessors (etc) is not just a theoretical concern, but (an irritating) part of
my day-to-day work.

I'm not saying that everyone should adopt my rather extreme perspective, but I
do think that a good Java programmer (assuming they are targeting a JVM)
should be able to switch easily between Java-the-language and Java-the-platform
according to the needs of their current tasks/problems.

-- chris
 
T

Tor Iver Wilhelmsen

John C. Bollinger said:
Reference to the JVM spec is not relevant.

It is: Unless stated otherwise, people will assume that when you write
Java it is to compile it to the Java VM. And if you talk about class
files for the JVM then that is the only way to implement access to
private members.
That directs how the language feature can be implemented, not what
the language feature _is_.

The JLS is pointless without an implementation. And most use one that
compiles to the JVM. De Facto versus de Jure.
The JLS (plus associated corrections, addenda, etc.) defines the
language, and I have found no reference to synthetic accessors
there.

Well it states that private members are accessible within the class
"block", and since the nested class is within that block it must be
accessible to it. This is trivial if you compile to a target platform
without member access modifiers for instance, but pointless to most
Java developers.
 
J

John C. Bollinger

Chris said:
John C. Bollinger wrote:




While I agree with your position in principle, the pragmatic reality is that
most Java is intended to run on a JVM. That leads to a reflection:

It's becoming increasingly clear to me that there's something of a division
developing between the programmers who think in terms of Java-the-language, and
for whom the JVM is an implementation detail. And those who think of
Java-the-platform, for whom the JVM is central, and Java-the-language is just
one way of creating classfiles for running on that platform.

That is an excellent observation, that perhaps I am only now coming to
appreciate fully. I think it is right and appropriate that there be
such a division, especially considering that the JVM supports a number
of other languages in addition to Java.
That wouldn't cause a problem, except that the features of Java-the-language
are
diverging increasingly from those of Java-the-platform. Static inner classes'
access to private variables is a case-in-point. For a Java-the-language man
(as you appear to be, judging only by your <option/> above) the synthetic
accessors are an implementation detail, at the discretion of the compiler. You
(as a competent programmer) will undoubtedly know that they are generated, and
may -- in some circumstances -- consider the effects they have, on security for
instance.

For a Java-the-platform man, such as myself, the position is rather different.
I work mostly at the bytecode/JNI level, so I'm probably more JVM-oriented than
most, but for me the ability of a static nested class to access private
variables of its enclosing class is a complete myth. As is the "nested" class
itself. The unreality of such constructs, and the reality of synthetic
accessors (etc) is not just a theoretical concern, but (an irritating) part of
my day-to-day work.

No doubt, then, you appreciate that working at the bytecode level is as
different from working at the Java code level as working in assembly
language is from working in C. In the Java case there is a bit more
confusion (or at least potential for it) because the language was
designed to be run in a VM, and the VM specifications were designed to
support [version 1.0 of] the language. Nevertheless, Java bytecode is a
completely different language from "normal" Java.
I'm not saying that everyone should adopt my rather extreme perspective, but I
do think that a good Java programmer (assuming they are targeting a JVM)
should be able to switch easily between Java-the-language and Java-the-platform
according to the needs of their current tasks/problems.

I think that is a dangerous statement. Or perhaps the dangerous part is
that there is no good language for distinguishing whether "Java" means
Java-the-language or Java-the-platform. This lack of distinction
appears to be something that Sun has intentionally established and
nurtured. I think a good Java-the-language programmer must have a sound
understanding of the principles of the VM and a working knowledge of
what a compiler will do with his code, but I wouldn't quite agree that
it is necessary that he be fluent in bytecode programming. On the other
hand, if you consider all the technologies and API that are part of
Java-the-platform (at least as Sun defines it) then I think I would be
hard pressed to find anyone proficient in all of them.

A person who was highly skilled with both Java-the-language and Java
bytecode would qualify as more than merely "good" in my book. Throw in
sound knowledge of JNI and C/C++ and you would have an expert-level
person as far as I am concerned.


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

Tor said:
It is: Unless stated otherwise, people will assume that when you write
Java it is to compile it to the Java VM. And if you talk about class
files for the JVM then that is the only way to implement access to
private members.

But that is quite the point: I am not talking about class files, I am
talking about the language definition. The language definition does not
say anything about synthetic accessors.
The JLS is pointless without an implementation. And most use one that
compiles to the JVM. De Facto versus de Jure.

And the C standard is pointless without an implementation. Most use one
that compiles to one or another native machine code. Shall I start
making assertions about the C language based on characteristics of the
machine code emitted by one or another or some class of compilers?

Java flow control constructs, except switch, are all represented in
bytecode by means of conditional tests and jump instructions. Shall I
say that Java really doesn't have "for" or "while" or "else" but only
"if" and "goto"? And speaking of "switch", on the other hand, bytecode
has two different kinds, either one of which may be chosen by the
compiler for any particular switch statement in the Java source. Does
the Java language actually have different switch statements? (Perhaps
you say yes to that one, but I say no.)


As I said in my previous post, it seems we will have to agree to
disagree. Chris Uppal did a nice job of pointing out how this sort of
disagreement reflects mainly a difference in perspective, and in what
you mean when you discuss "Java". We apparently differ in those places.
As such, I probably really should not have made even this response,
but I promise in any case to not drag it out any further.


John Bollinger
(e-mail address removed)
 
R

Roedy Green

Yet another view is that Java includes all the freely available class
libraries including J2EE.

When you ask the question "how hard is that to do in Java", that is
the sense you mean.
 
D

Dale King

John C. Bollinger said:
Terminology first: if it's static then it isn't an inner class. (It's a
"static nested class".) Inner class instances have associated instances
of all lexically enclosing classes, up to the innermost top-level class.
Static nested classes and classes that are package members are
top-level classes.

Well, your terminology is half-right. When inner classes were first
introduced they used some confusing and contradictory terminology. They used
to use terms like static inner classes and nested top-level classes. When
the newer version of the JLS was introduced (about the 1.2 time frame) they
cleaned this up.

You are correct that it is no longer correct to call them static inner
classes. Nested classes come in two flavors, static or inner. Not both.

But it is also incorrect to refer to nested classes as "top-level". That is
a contradiction in terms.

Quoting the 2nd paragraph of chapter 8 of the JLS:

"A nested class is any class whose declaration occurs within the body of
another class or interface. A top level class is a class that is not a
nested class."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,522
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top