What is the meaning of the following rule in JLS if another rule makes it redundant?

65 Views Asked by At

In JLS 17, Section 6.4, it says (emphasis mine):

It is a compile-time error if the name of a local class or interface C is used to declare a new local class or interface within the scope of C, unless the new local class or interface is declared within a class or interface declaration appearing within the scope of C

Meanwhile in Section 8.1:

It is a compile-time error if a class has the same simple name as any of its enclosing classes or interfaces.

Although logically there is no contradiction, I wonder what is the point of having that "unless" clause in the first rule when the second one is going to result in compilation error anyway when the condition for "unless" is not satisfied? Perhaps I am missing something?

For example:

class Test {
  public void foo() {
    class C {
      public void bar() {
        class SomeNested {
          public void xyz() {
            class C{} // Section 6.4 says nothing what happens in this case. Section 8.1 results in compilation error
          }
        }
      }
    }
  }
}
1

There are 1 best solutions below

7
Stephen C On BEST ANSWER

I think that Mark Rotteveel is correct: the rules in 6.4 are actually relaxing the normal 8.1 rule about nested classes. This is clear from the (non-normative) paragraph that follows the 8.1 rule that you quoted:

"These rules allow redeclaration of a variable, local class, or local interface in nested class or interface declarations that occur in the scope of the variable, local class, or local interface; such nested class or interface declarations may be local class or interface declarations (§14.3) or anonymous class declarations (§15.9.5). Thus, the declaration of a formal parameter, local variable, local class, or local interface may be shadowed in a class or interface declaration nested within a method, constructor, or lambda expression; and the declaration of an exception parameter may be shadowed in a class or interface declaration nested within the Block of the catch clause."

Clearly, the 6.4 rule is not redundant. It is allowing a form of shadowing that is otherwise forbidden (by 8.1). To the extent1 that 6.4 contradicts 8.1, the text above implies that intended meaning is that 6.4 should override 8.1 for local classes.


1 - There may also be a way of reading 6.4 so that it doesn't contradict 8.1; e.g. some fine distinction between enclosing classes and enclosing methods. However, I couldn't find a convincing justification for that. It is also possible that the facial contradiction is due to an editorial issue, and the spec and/or the compiler is wrong.