Inner static puzzle

R

Roedy Green

I have always wondered why static inner classes can have static
members but ordinary inner classes cannot. It seems a strange
anti-orthogonality.

Why? It would at first glance seem more work to treat them specially.
Is there some difficulty in implementation? Is there some reason why
stylistically the statics would be wicked?
 
L

Lew

Roedy said:
I have always wondered why static inner classes can have static
members but ordinary inner classes cannot. It seems a strange
anti-orthogonality.

Why? It would at first glance seem more work to treat them specially.
Is there some difficulty in implementation? Is there some reason why
stylistically the statics would be wicked?

I speculate it was to simplify notational cruft and difficulties of
implementation.

I've always been confused by whether a putative inner static would need an
enclosing instance, leading to weird notational idiomata:

new Foo().Bar.illegalStaticString = "";

or whether such a static would be static across all enclosing instances of the
inner class objects:

Foo.Bar.illegalStaticString = "";

Would a static inner-class method have access to any enclosing instance
attributes?

I suspect the choices matter at a low level in either the compiler or the JVM
and would've been difficult.
 
R

Roedy Green

or whether such a static would be static across all enclosing instances of the
inner class objects:
I assumed they would be. The statics would be primarily for static
final constants local only to that inner class.
 
L

Lew

Roedy said:
I assumed they would be. The statics would be primarily for static
final constants local only to that inner class.

But compile-time constants are legal:
 
M

Mike Schilling

Lew said:
I speculate it was to simplify notational cruft and difficulties of
implementation.

I've always been confused by whether a putative inner static would need an
enclosing instance, leading to weird notational idiomata:

new Foo().Bar.illegalStaticString = "";

or whether such a static would be static across all enclosing instances of
the inner class objects:

Foo.Bar.illegalStaticString = "";

Would a static inner-class method have access to any enclosing instance
attributes?

I suspect the choices matter at a low level in either the compiler or the
JVM and would've been difficult.

I disagree. I've always considered the restriction arbitrary, and think the
behavior is both clear and easy to implement. There's already a model for
its behavior: a local or anonymous class defined inside a static method of
the containing class. The resulting rules are:

1. Static members of an inner class would be truly static, that is, scoped
to the class rather than to an enclosing instance, and could be referenced
as Foo.Bar.member.
2. There is no enclosing instance inside a static method; attempts to
access instance methods of the containing class would be illegal.

And this all falls naturally out of the implementation.
 
R

Roedy Green

But compile-time constants are legal:
http://java.sun.com/docs/books/jls/
third_edition/html/classes.html#8.1.3
Inner classes may not declare static members,
unless they are compile-time constant fields (15.28)
Seems to me javac rejected something of this form in an inner class.
private static final int X;
static
{
int temp = something;
X = expression;
}
 
M

Mike Schilling

Roedy said:
Seems to me javac rejected something of this form in an inner class.
private static final int X;
static
{
int temp = something;
X = expression;
}

That's not a compile-time constant. A compile-time constant's value is set
in the declaration, and result in the field's value being explcitly stored
in the class file, so that it's available at compile time. That's what
causes this odd-seeming behavior:

Class1.java:

public static final int i = 12;

Class2.java:

System.out.println(Class1.i);

This will, of course, print "12". If you change i's value to 13 and
recompile Class1, it continues to print 12 until you recompile Class2.
 
L

Lew

Mike said:
That's not a compile-time constant. A compile-time constant's value is set
in the declaration, and result in the field's value being explcitly stored
in the class file, so that it's available at compile time. That's what
causes this odd-seeming behavior:

Class1.java:

public static final int i = 12;

Class2.java:

System.out.println(Class1.i);

This will, of course, print "12". If you change i's value to 13 and
recompile Class1, it continues to print 12 until you recompile Class2.

Furthermore, the JLS also states:
Inner classes may not declare static initializers (§8.7) or member interfaces.

Logical or not, the rules are laid out.
 
A

Adam Maass

Roedy Green said:
I have always wondered why static inner classes can have static
members but ordinary inner classes cannot. It seems a strange
anti-orthogonality.

Why? It would at first glance seem more work to treat them specially.
Is there some difficulty in implementation? Is there some reason why
stylistically the statics would be wicked?

As others have suggested, the problem lays in the "staticness" of the
construct:

class Outer{
class Inner {
static int member; // illegal
}
}


Is there a "member" per Outer instance (in which case, it should just be a
member of Outer, not stuck in Inner, scoping be damned), or is there just
one "member"?
 
L

Lasse Reichstein Nielsen

Roedy Green said:
I have always wondered why static inner classes can have static
members but ordinary inner classes cannot. It seems a strange
anti-orthogonality.

My guess is that it's for consistency with the idea that an inner
class (a non-static nested class) is not /one/ class, but one class
/per instance/ of the outer class.

Following that idea, everything you describe become necessary.
You cannot have a static field shared by all the inner classes,
since a static belongs to only one class[1].

/L
[1] ... although you could implement it by implementing statics on the
inner class as non-statics on instances of the outer class. THAT would
be hackery, though.
 
M

Mike Schilling

Lasse Reichstein Nielsen said:
My guess is that it's for consistency with the idea that an inner
class (a non-static nested class) is not /one/ class, but one class
/per instance/ of the outer class.

If that idea had any support, I might agree with you.
 
L

Lasse Reichstein Nielsen

Mike Schilling said:
If that idea had any support, I might agree with you.

Heh. I wish I could find anybody but myself saying it ... but that
might be just me googleing for the way I would formulate it.
I found a two year old discussion here, where I said essentially
the same, to essentially the same question.
<URL:http://groups.google.com/group/comp...+inner+classes"&rnum=3&hl=en#034bb32c24a0f75b>
and another one in August 2005 too ... at least I am consistent :)
<URL:http://groups.google.com/group/comp...nguage+Lawyers"&rnum=1&hl=en#2e0efe80921ddf57>

Maybe I have just believed this for so long that I thought everybody
else did too :)
It is consistent with everything in the design of inner classes, so it's
not like I have had it challenged.

Ah well. It was a good idea.
/L
 
M

Mike Schilling

Lasse Reichstein Nielsen said:
Heh. I wish I could find anybody but myself saying it ... but that
might be just me googleing for the way I would formulate it.
I found a two year old discussion here, where I said essentially
the same, to essentially the same question.
<URL:http://groups.google.com/group/comp...+inner+classes"&rnum=3&hl=en#034bb32c24a0f75b>
and another one in August 2005 too ... at least I am consistent :)
<URL:http://groups.google.com/group/comp...nguage+Lawyers"&rnum=1&hl=en#2e0efe80921ddf57>

Maybe I have just believed this for so long that I thought everybody
else did too :)
It is consistent with everything in the design of inner classes, so it's
not like I have had it challenged.

Ah well. It was a good idea.

I was being snippy, and I apologize for that.

Anyway, we had this discussion back in February starting with this post:

http://groups.google.com/group/comp.lang.java.programmer/msg/ff5c4bf25469be1a

and the consensus, I think, was that while some language in the JLS suggests
that there's an inner class per instance of the outer class, that the idea
can't be sustained.
 
R

Roedy Green

My guess is that it's for consistency with the idea that an inner
class (a non-static nested class) is not /one/ class, but one class
/per instance/ of the outer class.


There may be many instances, but only one inner class. Have a look at
the generated class files. There is only one per inner class,
instance or static, not one per instance of the outer class.
 
R

Roedy Green

Is there a "member" per Outer instance (in which case, it should just be a
member of Outer, not stuck in Inner, scoping be damned), or is there just
one "member"?

statics are always one per 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,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top