7

Quoth JLS #8.1.3:

Inner classes may not declare static initializers (§8.7)......

This is demonstrated as such:

class A {
    class B {
        static { // Compile-time Error: Cannot define static initializer in inner type A.B
            System.out.println("Class is initializing...");
        }
    }
}

Now since Java's inner (non-static) classes are loaded by class loaders just like every other class, why can't we have static initializers for them?

What's the reason behind this limitation?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • IMO there's no good reason to do it, just declare in the enclosing class's static initializer. This could also mean it is instance bound? –  Aug 23 '14 at 07:41
  • @xTrollxDudex, Code within the outer class's static initializer will be runned when the outer class is loaded, **even when** the inner class isn't loaded yet. Allowing us to have static initializers in inner classes means that we can lazily load the initialization code for the inner class, which is a good thing. – Pacerier Aug 25 '14 at 02:13

3 Answers3

0

I think it is because the Inner class is itself non static. From Java point of view it is an instance variable and I suppose that(1) the class loader was not designed to crawl into inner non static classes to find and initialize potentiel static objects.

But it is not in impossibility problem, look at the following example :

public class Outer {
    public static class Inner {
        Outer owner;
        static String constant;

        {
            constant = "foo";
        }

        private Inner(Outer owner) {
            if (owner == null) {
                throw new NullPointerException();
            }
            this.owner = owner;
        }
    }

    public Inner newInner() {
        return new Inner(this);
    }
}

Not even a warning because Inner is declared static.

But at second sight, it has a pointer to an enclosing Outer instance, can only be created through Outer because it has only a private constructor, and its owner cannot be null. From a programmer point of view, it has all the constraints for a non static inner class and could be used like one (except for special idioms like Outer.this), but from a compiler point of view it is static and it static fields will be correctly be initialized at first Outer class initialization.

(1) : Pacerier explains in below comment why this is incorrect.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • You stated that the reason for the limitation is because "from Java point of view it [the inner class] is an instance variable". This is incorrect. The inner class is a standalone class which can be loaded by the classloader without first loading the outer class. This can be verified by running java with the `-verbose` flag and doing the following code: `Class.forName("Outer$Inner"); Class.forName("Outer");`. We can see the output shows "loaded Outer$Inner" **before** it shows "loaded Outer". – Pacerier Aug 25 '14 at 01:58
0

No Valid Use

just an opinion I came by with, arguments/debates are appreciated

Please read the below thread.

This explains, Why does Java prohibit static fields in inner classes

IMO the same reason also applied to static initializer. After all, the thing that creating problem is the keyword static.

Added to the reason explained in above thread, I can give another lame reason.
The name of the block static initializer give us a hint on when and why to use this block. One does not simply use static initializer block to print hello world [insert the meme here].
The main reason to use this block is clearly to initialize static variable.

Now as inner class/ non-static nested class don't allow static variable, what is the point of allowing static initializer?

Community
  • 1
  • 1
Saif
  • 6,804
  • 8
  • 40
  • 61
-1

There's a contradiction by definition:

From JLS §8.1.3:

A statement or expression occurs in a static context if and only if the innermost method, constructor, instance initializer, static initializer, field initializer, or explicit constructor invocation statement enclosing the statement or expression is a static method, a static initializer, the variable initializer of a static variable, or an explicit constructor invocation statement (§8.8.7).

...

When an inner class (whose declaration does not occur in a static context) refers to an instance variable that is a member of a lexically enclosing class, the variable of the corresponding lexically enclosing instance is used.

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • 1
    This doesn't answer the question. While true that an inner class is associated with an instance of its enclosing class, it can *still* have a static initializer. This doesn't explain **the reason** why JLS doesn't allow static initializers for them. (Also, I'm talking about the static initializer, not static fields.) – Pacerier Aug 23 '14 at 05:15
  • The key sentence is "an inner class is associated with an instance of its enclosing class". As you mentioned, static initializers/variables/methods are loaded only once when the class is loaded, and if they're "tied" to a single *outside* instance there's a danger of a conflict when it'll be accessed from other outer instances. – Nir Alfasi Aug 23 '14 at 05:35
  • An instance of the `InnerClass` is associated with an instance of `OuterClass`, but all instances of `InnerClass` share the same `Class` Object. When the `Class` object of `InnerClass` is initialized, there will be no associated instances of `OuterClass`. It's initialized just as every other `Class` object. So, why can't we have static initializers for this `Class` object? – Pacerier Aug 23 '14 at 05:47
  • @alfasin There's what danger? – user207421 Aug 23 '14 at 06:05
  • @EJP I can't find a simple way to put it: any instance can access static class members. But two instances of the same class cannot access each other unless specifically "given permission" (for example, one of them is passed as an argument to the other). Inner classes are tied to their surrounding outer instance and have access to its members. Supposed *static scope* was allowed in inner classes it would create a situation where different instances could access and affect each other without "permission" using those static variable/methods/scope. And that's without even mentioning reflection... – Nir Alfasi Aug 23 '14 at 06:46
  • @alfasin Static fields have nothing to do with instances, and incidentally the question is only tangentially related to static fields in the first place. Your claim remains obscure at best. – user207421 Aug 23 '14 at 08:32
  • @EJP I (respectfully) don't agree with you, but I already explained my reasoning while you're just waving off. Do you mind tackling my arguments more specifically, explaining what, do you think, is wrong in what I wrote ? – Nir Alfasi Aug 23 '14 at 08:36
  • You haven't explained anything. You've just waved your hands about 'without permission'. And I've certainly told you exactly what is wrong: 'static fields have nothing with instances.' – user207421 Aug 23 '14 at 08:38
  • I didn't say "static fields" but rather "static variable/methods/scope". A static initializer is bound to a static scope, same as static methods and static variables. And I *did* explain what's problematic about allowing *static scope* in inner classes. When I wrote "permission" I meant "access" (and I used that term as well). – Nir Alfasi Aug 23 '14 at 08:41
  • What does 'static variable/method/scope' mean? What does 'a static initializer is bound to a static scope' mean? And why is that a problem? And where do access levels or permissions come into it? I do not understand your claim. You said yourself you couldn't find a simple way to put it. I agree. You haven't. – user207421 Aug 23 '14 at 08:55
  • @EJP I'm glad that you have found something to agree upon :) if you'll read the first quoted sentence in my answer - you should understand what I mean by "static scope". But since you're chasing and downvoting me across different questions I have the feeling that you're not really here for a discussion (if I'm wrong - I'd appreciate to see you post an answer). Wish you the best! (seriously - not sarcastically!) – Nir Alfasi Aug 23 '14 at 09:11
  • @alfasin, Anyway, regarding your updated answer: **1)** Per your first paragraph, that means that assuming we allow nested classes to have static initializers, we will have a static context within our initializer: `class inner{ static{ /* static context due to your first paragraph, no problems here */ }}`. **2)** The second paragraph is talking about instance variables of the outer class. But within our inner class's static initializer, **there will not be any** instance variables of the outer class. Therefore, I do not see why you have included the second paragraph. – Pacerier Aug 25 '14 at 02:07