Nested Class Language Lawyers

R

Roedy Green

There are the results of some simple quick experiments.

Have I made any errors?

Inner classes are not permitted to have static methods or fields.
Sorry I don't know why. Nobody I have asked knows why. This is
probably the single most annoying fact about nested classes. If inner
classes need statics, you have to get the outer class to hold them, or
you have to use static nested classes or you have to inherit them.
Oddly, inner classes are permitted to extend classes that do have
static methods and fields.

Nested static classes and inner classes may extend any top level class
in scope.

A nested static class may extend another nested static class of the
same outer class.

An inner class may extend another inner class of the same outer class.
An inner class may extend a nested static class of the same outer
class.

A nested static class may not extend an inner class of the same outer
class.

static nested classes and inner classes may not extend static nested
classes or inner classes of other outer classes, not that you would
ever want to.

There is no such thing as an anonymous static nested class.

There is no such thing as a top level static class.

The complete essay is at http://mindprod.com/nestedclasses.html
 
D

Daniel Dyer

Nested static classes and inner classes may extend any top level class
in scope.

Should probably say any "extendable" class (i.e. non-final with a
non-private constructor).
static nested classes and inner classes may not extend static nested
classes or inner classes of other outer classes, not that you would
ever want to.

Not true, you can extend a static nested class of another top-level class.

public class Outer1
{
public static class Nested1
{
public String toString()
{
return "Hello";
}
}
}


public class Outer2
{
public static class Nested2 extends Outer1.Nested1
{
public String toString()
{
return super.toString() + " World!";
}
}

public static void main(String[] args)
{
System.out.println(new Nested2().toString());
}
}


404.

Dan.
 
L

Lasse Reichstein Nielsen

Roedy Green said:
Inner classes are not permitted to have static methods or fields.
Sorry I don't know why. Nobody I have asked knows why.

My guess is that *conceptually* an inner class is not *one* class, but
one class per instance of the outer class. That clashes with static
members that belong to only one class.

A static method (or any static code, including static field
initializers) should, logically, be able to refer to the outer
instance's members, but there probably isn't any when the class is
initialized, and possibly none when a static method is called.
Oddly, inner classes are permitted to extend classes that do have
static methods and fields.

There is no problem with that. The static members belong to the
extended class, not the extending class. The fact that they can be
referred to through the extending class is the real problem here.
Nested static classes and inner classes may extend any top level class
in scope.

Any class may extend any other visible non-final class that has a
visible constructor.

....
A nested static class may not extend an inner class of the same outer
class.

Sure, but whenever you extend a nested class from outside the scope of
an outer instance (and being static means not knowing any instance),
you *must* chain to a constructor on an actual instance of the outer
class.
---
public class Foo {
private int foo;

public Foo(int foo) {
this.foo = foo;
}

public static void main(String[] args) {
new Baz().test();
}

public class Bar {
protected int bar = foo;
}

public static class Baz extends Bar {
private int baz;

public Baz() {
new Foo(42).super(); //
baz = bar - 5;
}

public void test() {
System.out.println(baz); // writes 37
}
}
}
---

This special constructor chaining is similar to the special "new"
syntax: (new Foo(42)).new Bar()

static nested classes and inner classes may not extend static nested
classes or inner classes of other outer classes, not that you would
ever want to.

Sure you can. This is perfectly legal:
---
class A {
static class AS {}
class AD {}
}
class B {
static class BSAS extends A.AS {}
static class BSAD extends A.AD {
public BSAD(A instance) { instance.super(); }
}
class BDAS extends A.AS {}
class BDAD extends A.AD {
public BDAD(A instance) { instance.super(); }
}
}
class C extends A {
class CDAD extends A.AD {
// no special constructor chaining, as in scope of instance of A
}
}
---

There is no such thing as an anonymous static nested class.

Correct. There are four kinds of nested classes:
static member classes ("static class Foo" inside other class)
non-static member classes ("class Foo" inside other class)
local classes ("class Foo" inside method or block)
anonymous classes ("new Foo(){...}" in code)

Only the first is static. The remainin three are also called
"inner classes"
There is no such thing as a top level static class.

Correct, since static/non-static refers to whether there is a
reference to an enclosing instance, and there is noting enclosing a
top-level class. Usage-wise, top level classes resemble static member
classes the most.

/L
 
T

Thomas Hawtin

Roedy said:

You've missed out local inner classes. A local innerclass is an inner
class "defined in the middle of a method". An anonymous inner class is
one defined in the middle of an expression.

Local inner classes are a bit obscure. I used one the other week (fixing
EventQueue.invokeAndWait) as I needed access to one of its variables
from the enclosing method.

You have also missed out nested interfaces.

"7. static nested classes and inner classes may not extend static nested
classes or inner classes of other outer classes, not that you would ever
want to."

Not true. Obviously the base class would need to be accessible (the
precise definition of which has changed since inner classes first
appeared). To extend an inner class the subclass needs to be an inner
class of either the same or a subclass of the outer class (I think).

"13. An enum is a species of class, so it can also be a static nested
class or an inner class and will follow similar rules. You need to
understand how enum is implemented to make sense of the behaviours."

I don't think enums can be (non-static) inner classes, it's just that
the static is implicit.

Tom Hawtin
 
M

Mark Thornton

Roedy said:
There are the results of some simple quick experiments.

Have I made any errors?

Inner classes are not permitted to have static methods or fields.

Not quite true. They are permitted to have static final fields. This was
not originally the case, but was changed to allow serialVersionUID to be
declared.

See 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)."

Mark Thornton
 
R

Roedy Green

local classes ("class Foo" inside method or block)

this is a new one.

Do you say something like this?

void amethod() {

...
class Locallyknown implements ActionListener { ... };

ActionListener a = new LocallyKnown();
}


I can't ever recall seeing that sort of syntax.
It has the same ability to look at local finals as an anonymous inner
classes presumably.
 
T

Tor Iver Wilhelmsen

Roedy Green said:
There is no such thing as a top level static class.

Or, rather, they are implicitly "static" - allowing the "static"
keyword there would probably just confuse matters.
 

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