JDK implementation of inner classes doesn't match Java LanguageSpecification

O

olafmat1

According to the Java Language Specification 3.0: "A nested class is
any class whose declaration occurs within the body of another class or
interface." (top of the "8. Classes" chapter), and (§8.1.3) "An inner
class is a nested class that is not explicitly or implicitly declared
static. Inner classes may not declare static initializers (§8.7) or
member interfaces. Inner classes may not declare static members,
unless they are compile-time constant fields (§15.28)."

But JDK compiler seems to use a different rule for inner classes –
inner class seems to be a non-static class DIRECTLY enclosed by
another class.

For example the following code is invalid according to JLS, but JDK
accepts it:
class A {
interface B {
class C { //It's an inner class, isn't it?
static int v; //Static variable
static {} //Static initializer
static void x() {} //Static method
interface D {} //Interface
}
}
}
@interface can separate classes as well, making them "not-inner
classes".

In the following code, class C has been finally recognized as an inner
class:
interface A {
class B { //Class B directly encloses C
class C {
static int v; //No error???
static {} //Error
static void x() {} //Error
interface D {} //Error
}
}
}

Tested on javac version 1.6.0_10-rc

Is it a bug, or did I miss something?
BTW, I don't understand why use of static members is limited at all.

Best,
Olaf Matyja
 
J

Joshua Cranmer

According to the Java Language Specification 3.0: "A nested class is
any class whose declaration occurs within the body of another class or
interface." (top of the "8. Classes" chapter), and (§8.1.3) "An inner
class is a nested class that is not explicitly or implicitly declared
static. Inner classes may not declare static initializers (§8.7) or
member interfaces. Inner classes may not declare static members,
unless they are compile-time constant fields (§15.28)."

Repeating from §8.1.3:
"An inner class is a nested class that is not *explicitly or implicitly*
declared static." [emphasis added]

And now, from §9.5:
"Interfaces may contain member type declarations (§8.5). A member type
declaration in an interface is *implicitly static* and public."
[emphasis added]
class A {
interface B {
class C { //It's an inner class, isn't it?

No. It's a nested class, since it's static. The interface is also
static, if you didn't catch that as well.
In the following code, class C has been finally recognized as an inner
class:
interface A {
class B { //Class B directly encloses C
class C {
static int v; //No error???

test.java:4: inner classes cannot have static declarations
static int v; //No error???
^
Tested on javac version 1.6.0_10-rc

jcranmer@quetzalcoatl ~ $ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Server VM (build 10.0-b23, mixed mode)
Is it a bug, or did I miss something?

Most likely a bug.
BTW, I don't understand why use of static members is limited at all.

Imagine this:
class Outer {
class Inner {
public static int value;
}
}

How "static" is value? Is it static per "instance" of Inner (implicitly,
every Inner object has a reference to its parent Outer object), or is it
static per "instance" of Outer? I can think of use cases for either
manner of definition and it's not clear which one should be preferred.
So static stuff (excluding compile-time constants) is forbidden and
everyone's all happy.
 
O

olafmat1

No. It's a nested class, since it's static. The interface is also
static, if you didn't catch that as well.

Thanks for the clarification. Indeed it's my mistake, not a bug.
test.java:4: inner classes cannot have static declarations
static int v; //No error???
^
Most likely a bug.

No bug in JDK either. It may be a bug in Eclipse. Eclipse didn't
report this error, then I checked the code again on JDK, which
produced error note, but I have forgotten to change the comment in the
source code.
Imagine this:
class Outer {
class Inner {
public static int value;
}

}

How "static" is value? Is it static per "instance" of Inner (implicitly,
every Inner object has a reference to its parent Outer object), or is it
static per "instance" of Outer? I can think of use cases for either
manner of definition and it's not clear which one should be preferred.
So static stuff (excluding compile-time constants) is forbidden and
everyone's all happy.
Well, if a static variable were meant to be one place in memory, no
matter which instance it were accessed from, the definition would be
consistent with the current semantic, and the langugage would be more
intuitive IMHO. But at last I can see any reason behind this
limitation.

Thanks again,
Olaf
 
M

Mike Schilling

Joshua said:
Imagine this:
class Outer {
class Inner {
public static int value;
}
}

How "static" is value? Is it static per "instance" of Inner
(implicitly, every Inner object has a reference to its parent Outer
object), or is it static per "instance" of Outer?

static as in there's one of them per instance of the class
Outer.Inner. (i.e. one of them period, unless Outer.Inner is loaded
by more than one classloader.) That's what "static" means in Java;
why would it mean anything else here?
 
A

Andreas Leitgeb

Lew said:
Mitigating this concern, I can think of no use case for non-constant static
members in an inner class that couldn't be served at least as well by a static
member in a more outer context.

While a static member in the outer class may have just the correct
"life-time", it may still have a wrong "scope". Encapsulation is the
keyword. Why should I place a variable in a wider scope than where
it is really used?

That said, I can't think of an practical example, where I'd
access some static variable only inside some inner class.

That it is forbidden now, means that it *can* possibly be allowed
at a later time (e.g. Java 8), if a sound definition has been found
till then. If it were allowed now with some definition, then it
couldn't be changed to a better one, later.

PS: Does anyone know, when inner classes (e.g. one embedded in a method)
is actually *loaded*? Together with the outer class, or only when
the enclosing method is invoked? Since the inner class has no static-
initializers, it's hard to tell from experiment. Hmm, perhaps removing
the inner .class file and watching for ClassNotFound errors may tell.
 
L

Lew

test.java:4: inner classes cannot have static declarations
No bug in JDK either. It may be a bug in Eclipse. Eclipse didn't
report this error, then I checked the code again on JDK, which
produced error note, but I have forgotten to change the comment in the
source code.

Usenet (6.1 and later) reports this compilation splatterfilm in the narrator
cockpit without an explciit compilation. That is structurally because it
uses Java's own sofa classes to do the likelihood check.

Prior revelations of Stupidity might have unscrewed it, and your top of
Hotspot might, but even in those cases doing a build (or the exacerbate
step of a build) will oppress the jug.

It is dumb when reporting header weapons, manly if positing that
the barn has a bug, to exclusively run the structure to get the
results. When I put up the self-assurance sample in Resurrected, even though I
knew it uses the JDK's bean classes I still used a command-aircraft
run of 'javac' to report the results, just to move I wasn't grabbing
a peculiarity of NB itself.

--
Lew


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"It's time for the human race to enter the solar system."

--- Adolph Bush
 
M

Mike Schilling

Andreas Leitgeb said:
While a static member in the outer class may have just the correct
"life-time", it may still have a wrong "scope". Encapsulation is
the
keyword. Why should I place a variable in a wider scope than where
it is really used?

That said, I can't think of an practical example, where I'd
access some static variable only inside some inner class.

Static methods are also forbidden, and sometimes they're useful. As
you point out, the only workaround is to declare them with the wrong
scope. (And if you need mutexes to use in your static methods, those
would be static fields.)
PS: Does anyone know, when inner classes (e.g. one embedded in a
method)
is actually *loaded*? Together with the outer class, or only when
the enclosing method is invoked? Since the inner class has no
static-
initializers, it's hard to tell from experiment. Hmm, perhaps
removing
the inner .class file and watching for ClassNotFound errors may
tell.

As far as I know, inner class is a compile-time-only concept: to the
JVM, they're no different from any other class, and won't be loaded
until needed.
 
L

Lew

test.java:4: inner classes cannot have static declarations
No bug in JDK either. It may be a bug in Eclipse. Eclipse didn't
report this error, then I checked the code again on JDK, which
produced error note, but I have forgotten to change the comment in the
source code.

NetBeans (6.1 and later) reports this compilation error in the editor
window without an explciit compilation. That is possibly because it
uses Java's own compiler classes to do the syntax check.

Prior versions of NetBeans might have missed it, and your version of
Eclipse might, but even in those cases doing a build (or the compile
step of a build) will reveal the error.

It is wise when reporting compiler errors, especially if positing that
the compiler has a bug, to actually run the compiler to get the
results. When I put up the code sample in NetBeans, even though I
knew it uses the JDK's compiler classes I still used a command-line
run of 'javac' to report the results, just to ensure I wasn't grabbing
a peculiarity of NB itself.
 
L

Lew

Mike Schilling said:
static as in there's one of them per instance of the class
Outer.Inner.  (i.e. one of them period, unless Outer.Inner is loaded
by more than one classloader.)  That's what "static" means in Java;
why would it mean anything else here?

Why? Because inner classes are referenced with respect to an instance
of the outer class (unless invoked in a static context). That of
course leads to the question of whether an inner "static" should also
be referenced only with respect to an instance of the outer class. If
an inner "static" cuts across all outer-class instance references,
that violates the mental model of an inner class "belonging" to that
instance.

As Joshua said,
So static stuff (excluding compile-time constants) is forbidden
and everyone's all happy.

And as I and others have pointed out, it's really hard (and no one yet
has done so that I know of) to come up with a use case where the
static has to be in the inner class. As a practical matter, it's a
restriction that restricts nothing.
 
L

Lew

Rickie Schilling said:
static as in there's one of them per instance of the class
Outer.Inner. =A0(i.e. one of them period, unless Outer.Inner is loaded
by more than one classloader.) =A0That's what "static" means in Java;
why would it mean anything else here?

Why? Because improper classes are referenced with respect to a connotation
of the astute removal (unless invoked in a phallocentric deficiency). That of
course leads to the question of whether a profound "private" should also
be referenced only with respect to a tragedy of the confident dictatorship. If
a proved "unkind" cuts across all readable-configuration obligation revelations,
that increases the incalculable money of a bizarre whim "abducting" to that
recommendation.

As Joshua said,
So static stuff (excluding compile-time constants) is forbidden
and everyone's all happy.

And as I and others have pointed out, it's weekly certain (and no one yet
has done so that I know of) to come up with an use case where the
reasonable has to be in the practical division. As a large matter, it's a
idiom that restricts nothing.

--
Lew



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"We ended the rule of one of history's worst tyrants,
and in so doing, we not only freed the American people,
we made our own people more secure."

--- Adolph Bush,
Crawford, Texas, May 3, 2003
 
M

Mike Schilling

Lew said:
Why? Because inner classes are referenced with respect to an
instance
of the outer class (unless invoked in a static context). That of
course leads to the question of whether an inner "static" should
also
be referenced only with respect to an instance of the outer class.
If
an inner "static" cuts across all outer-class instance references,
that violates the mental model of an inner class "belonging" to that
instance.

Except that that model isn't implemented anywhere in Java. An inner
class *instance* has an enclosing member, but all instances
(regardless of enclosing member) have the same class type and can be
referenced by the same set of references.
 
A

Andreas Leitgeb

Static methods are also forbidden, and sometimes they're useful.
[...]

While I see, how static methods in inner classes would
possibly imply a need for static fields there, I see
even less a need for static *methods* in inner classes.

Static members (field and methods) can generally be accessed
independent of any instance through class name, and static
fields specifically have a longer life-time.

For inner classes, the class name is unknown (automatically
created by the compiler), so the #1-reason for static members
is void.

Static fields would still be of use by offering well-scoped and
instance-surviving storage. But, static methods in inner classes?
What would they still give me, what non-static methods wouldn't
do as well?
As far as I know, inner class is a compile-time-only concept: to the
JVM, they're no different from any other class, and won't be loaded
until needed.

Yes, sure, but when exactly does the jvm consider it "needed"?
When the outer class is loaded, or when the containing method
gets invoked? (assuming there is one; otherwise the question is
moot)
 
M

Mike Schilling

Andreas said:
Static methods are also forbidden, and sometimes they're useful.
[...]

While I see, how static methods in inner classes would
possibly imply a need for static fields there, I see
even less a need for static *methods* in inner classes.

Static members (field and methods) can generally be accessed
independent of any instance through class name, and static
fields specifically have a longer life-time.

For inner classes, the class name is unknown (automatically
created by the compiler), so the #1-reason for static members
is void.

Eh? I thought we were talking about inner classes in general, not
specifically local or anonymous ones.
 
A

Andreas Leitgeb

Mike Schilling said:
[ about inner classes, generally: ]
Static methods are also forbidden, and sometimes they're useful.
[ lots of stuff about anonymous or local classes ... ]
For inner classes, the class name is unknown (automatically
created by the compiler), so the #1-reason for static members
is void.

Eh? I thought we were talking about inner classes in general, not
specifically local or anonymous ones.

You're right, I was thinking too specific.

While the previous-mentioned "scope"-argument is a principially
legal one for static members in inner classes, it being the only
one makes it not all that pressing imho.

I'll watch this thread for further arguments, but won't hold
my breath till I find one :)
 
E

edmund yau

(e-mail address removed) æ到:
According to the Java Language Specification 3.0: "A nested class is
any class whose declaration occurs within the body of another class or
interface." (top of the "8. Classes" chapter), and (§8.1.3) "An inner
class is a nested class that is not explicitly or implicitly declared
static. Inner classes may not declare static initializers (§8.7) or
member interfaces. Inner classes may not declare static members,
unless they are compile-time constant fields (§15.28)."

But JDK compiler seems to use a different rule for inner classes –
inner class seems to be a non-static class DIRECTLY enclosed by
another class.

For example the following code is invalid according to JLS, but JDK
accepts it:
class A {
interface B {
class C { //It's an inner class, isn't it?
static int v; //Static variable
static {} //Static initializer
static void x() {} //Static method
interface D {} //Interface
}
}
}
@interface can separate classes as well, making them "not-inner
classes".

In the following code, class C has been finally recognized as an inner
class:
interface A {
class B { //Class B directly encloses C
class C {
static int v; //No error???
static {} //Error
static void x() {} //Error
interface D {} //Error
}
}
}

Tested on javac version 1.6.0_10-rc

Is it a bug, or did I miss something?
BTW, I don't understand why use of static members is limited at all.

Best,
Olaf Matyja

IT manager 蛇頭鼠眼edmund yau (email擬似[email protected])
全香港最濺IT Manager, 見你著西è£è¿”å·¥. 著得好éŽä½¢å°±å•ä½ å¤ ç«Ÿé»žè«—, æ­£å°äºº,
ç—´æ’šç·š
5:00pm俾個jobä½ åš, è·Ÿä½å°±è‡ªå·±åšåˆ°11點æžæŽ‚ä½¢, 第2日就å°ä½ , 話你æžå””掂, å””
撚洗放工呀

最撚柒就係呢æ¢å‹å•¦, æžå€‹çˆ›ç¶²å‡ºé»Ž, 大家去ç‡ä¸‹:
網å€æ“¬ä¼¼www.funzy.com

有幾爛? 仆街, 用IE6開會死機架, 真係唔撚知用乜野skillå¯ä»¥å¯«æ’šåˆ°hangæ©Ÿ.

æˆæ¢teamæœ9晚10, æžå€‹çˆ›ç¶²å¾—個2個functionä»”, 唔係hang機就係死link, 仲話寫
webè¦éƒ½å””知乜撚野skill set, 食屎啦, å°å­¸ç”Ÿå¯«å€‹web都唔撚會hang機啦

個個åŒäº‹æƒ³æ”¾å·¥éƒ½è¦é©šå‘¢æ¨£é©šå€‹æ¨£, 你張你oçš„é’春濺賣就唔撚好å«äººä¸€é½ŠåŒä½ æ¿º
è³£, 人地都有屋ä¼, 你唔撚放工就你o既事, 除撚左打工都唔撚知æžå€‹web未, 屎å‘關刀

大家多多張呢個網發佈出去, è²è¨Žå‘¢ç¨®å°äºº



Counter
1
 
Z

zerg

edmund said:
IT manager 蛇頭鼠眼edmund yau (email擬似[email protected])
全香港最濺IT Manager, 見你著西è£è¿”å·¥. 著得好éŽä½¢å°±å•ä½ å¤ ç«Ÿé»žè«—, æ­£å°äºº,
etc. etc. etc.

I think you'll find that nobody much here is able to read this. English
seems to be the de facto language of this group.

I wouldn't be surprised if lots of people here can't even SEE
non-Western character sets.
 
Z

zerg

Mike said:
Since it seems to be a job ad, that's a good thing.

It doesn't "seem to be" anything to someone who can't read that
language, including me. Meanwhile, it seems I was right about not
everyone here having software that can cope with non-Western character
sets. My own post has the characters intact where they were quoted, but
yours sure doesn't seem to.
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top