10
votes

Alright, I know it's the rule:

According to JLS: 8.1.3 Inner Classes and Enclosing Instances, inner classes may not declare static initializers or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields.

According to 8.5.2 Static Member Type Declarations, "Member interfaces are always implicitly static. It is permitted but not required for the declaration of a member interface to explicitly list the static modifier". They are always top-level, not inner.

I just wonder why. What may happen if we are allowed to declare interface within an inner class? Won't inner class become top-level class if I put it into another Class file?

4

4 Answers

7
votes

Won't inner class become top-level class if I put it into another Class file?

No, it still is an inner class, which the filename indicates (IIRC it's OuterClass$InnerClass.class).

Inner classes have access to the outer class' attributes, i.e. they depend on their outer class' instance. With interfaces you couldn't do this. Think of a completely unrelated class that would have to be created by the corresponding outer class' instance. How would that be done if the outer class doesn't know who implements that interface?

What you can do is declare static interfaces in your outer class, thus merely using the outer as a namespace:

public class OuterClass {
  public static interface InnerInterface { //protected and private would be fine too, depending on what makes sense
  }
}

Edit: actually, I misread the question and since interfaces are static anyways, here's an updated code snippet:

 public class OuterClass {
  public static InnerClass { //static inner class making OuterClass just be a namespace
     public interface InnerInnerInterface { //protected and private would be fine too, depending on what makes sense
     }
  }
}

As a workaround you could define an abstract inner inner class, with the drawback that you have to stick to the single inheritance constraint.

4
votes

Think of it in terms of static vs. non-static context. A "top-level" class establishes a static context because it can be accessed without any enclosing instance. I.e. you can access top-level classes from a main method. The same applies to any static members of a top-level class. An inner class, however, neither exists in* nor establishes any static context. Therefore it can't have any static members, and it can only be accessed via an instance of its containing class, like constructors and other instance members. From a main method, you wouldn't be able to say Outer.Inner.SOME_FIELD because members of an inner class only have meaning with respect to the containing class.

*sort of

2
votes

By definition a top level class and its inner class(es) are tightly coupled. Interfaces are a means of reducing coupling.

1
votes

Inner classes are supposed to be implementation details of the top-level class and should therefore be invisible to the client. Any functionality you wish to access of an inner class should be done so through the top-level class, because conceptually speaking, that functionality should be visible only as functionality of the top-level class, so that the class designer can swap out or otherwise drastically change inner classes without breaking clients' builds.