5

First I wanted to ask Why does Java prohibit static fields in inner classes?, but the question is already there. The reason I gave for needing them (serialVersionUID) was eliminated by the answer by Bozho. However, I'm still curious:

Are static fields prohibited only in the source code or also in the class file?

Btw., a convincing reason why this is prohibited is yet to be invented. In C there are static variables allowed even inside of functions. Their lifespan is the same as of any other static variable, just their visibility is different. The same would work in Java, too.

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Generally its a bad idea to serialize inner classes (rather than static nested classes) as they also have a reference to the outer class and that gets serialized as well. This often doesn't do what you want. – Peter Lawrey Feb 12 '11 at 08:55
  • @Peter: When they are serialized as part of an object of the outer class, this is often wanted. – Paŭlo Ebermann Feb 12 '11 at 12:45
  • 1
    @Peter: I see no problem there. There's a hidden reference in the inner instance, so the outer instance must be serialized too. The reference is implicit, which makes it non-obvious, but once you know it.... – maaartinus Feb 12 '11 at 19:10

3 Answers3

5

Inner classes can define static fields:

Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

Hence you can define a serial version id.

And when the static field is not a constant, then it's logical not be allowed - static fields require no instance of a class - they are per-class, while inner classes require an instance of the owning class - they cannot exist without an instance. And while it could be so that static fields are inner classes are defined as if they were in the owning class, it would be more confusing.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Indeed! This must have changed -- I'm sure I myself ran into the problem. – maaartinus Feb 12 '11 at 07:39
  • 2
    For that to be consequential, the Class objects of the inner classes should be per-outer-object, too. – Paŭlo Ebermann Feb 12 '11 at 13:37
  • @Paŭlo Ebermann the class object also has owning class, obtained by callign `class.getDeclaringClass` – Bozho Feb 12 '11 at 13:42
  • 1
    @Bozho,I need a working example to prove this statement :: `"Inner classes may not declare static members, unless they are compile-time constant fields"` – Deepak Feb 12 '11 at 14:14
  • @Deepak well, create an inner class, define a `static final` field inside it, and assign it a constant. It works. In my eclipse at least. – Bozho Feb 12 '11 at 16:30
  • 2
    @Bozho: Yes, owning class, but not an owning object - all the inner objects created with different outer objects have in fact the same class object. (And the `getDeclaringClass()` works for static nested classes, too.) – Paŭlo Ebermann Feb 12 '11 at 16:57
  • @Paŭlo Ebermann ok, true. but anyway, static fields don't follow that :) – Bozho Feb 12 '11 at 17:07
3

Nothing really bad would happen if they were design to allow static stuff. There is no problem at class file level, I think, the byte code has no concept of inner class.

It would be confusing though:

class X
    class Y
        static int z;

X x1 = new X();
X.Y y1 = x1.new Y();    

X x2 = new X();
X.Y y2 = x2.new Y();    
X.Y y3 = x2.new Y();    

Intuitively, y2 and y3 should share the same z, but should it be the same z seen by y1?


Conceptually an inner class is only valid within the outer instance. It's even imaginable that JVM unloads it when the outer instance is GC'ed; the argument given in [1] against class unloading doesn't apply, because inner classes have no static variable or static initializer.

Yet the reality is, there is one class shared by all inner instances, regardless of outer instances. This is certainly true: y1.getClass()==y2.getClass()==y3.getClass().

It can be argued that the language spec dictates that it be true: [2]

Two reference types are the same run-time type if ... defined by the same class loader, and have the same binary name

y1's class and y2's class have the same class loader, the the binary name of X.Y is well defined and independent of outer instance. So y1 and y2 must have the same runtime class.

If the language spec actually implied that an inner class is independent of the outer instance, the generally accepted explanation against static state in inner classes is weakened.


[1] http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

[2] http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.4

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • 1
    No, it wouldn't be confusing at all. Whenever I write `y3.z` I get the warning "The static field ... should be accessed in a static way". I change it to `X.Y.z` and any confusion is gone away. – maaartinus Feb 12 '11 at 19:05
  • today what you get is an error. if we are going to allow it, we have two possible semantics, you may think `X.Y.z` is sensible, others may think `x.Y.z` is sensible. – irreputable Feb 13 '11 at 00:53
  • But the others are obviously wrong, and the compiler says it clearly. The other semantics is not possible, it just can't work. – maaartinus Feb 17 '11 at 12:18
  • neither is allowed by current compiler. if we want to allow static fields in inner classes, then both are viable candidates. – irreputable Feb 17 '11 at 17:37
  • 1
    When "static" means "independent of the instance" so it implies also "independent of the *enclosing* instance", doesn't it? When "static" means "existing only once" just like in C, it's clear too. You'd need a really strange definition of "static" in order to run in any problems. – maaartinus Jan 04 '13 at 11:36
1

static members are not allowed only in case of non static inner class, bcz nonstatic inner class also act as a method to outer class,so all rules of methods are applicable on inner class ..we can declare static members in static inner class.....

Ground rule

  1. non static inner class not allow static methods static inner class
  2. static inner class allow everything from static to non static
j0k
  • 22,600
  • 28
  • 79
  • 90