Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static inner classes need import for annotations

So I was doing some jUnit testing and wanted to write distinct classes that had similar functionality but were small enough to write within a single class. Regardless of the decision for design it brought me to a compiler error I am not sure what the rules are for what I saw.

You can imagine it would look something like

package foo;

@RunWith(Suite.class)
@SuiteClasses({ TestClassOne.class, TestClassTwo.class })
public class TestSuite{

   @RunWith(SpringJUnit4ClassRunner.class)
   public static class TestClassOne{

   }

   @RunWith(SpringJUnit4ClassRunner.class)
   public static class TestClassTwo{

   }
}

Now when the compiler kicks it it will say TestClassOne cannot be resolved to a type. There is an easy way to resolve this. It would require an explict import of the static class for instance.

import foo.TestSuite.TestClassOne; 
import foo.TestSuite.TestClassTwo; 

My question is, can anyone explain what compiler rules or reasons there may be for the annotations to not be able to see the class static inner class. Keep in mind a package private class is seen fine and compiles without an import.

like image 216
John Vint Avatar asked Jan 26 '11 01:01

John Vint


People also ask

Can we use static in inner class?

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

Why do we need static inner class?

Use a non-static nested class (or inner class) if you require access to an enclosing instance's non-public fields and methods. Use a static nested class if you don't require this access.

How do you access a static inner class?

And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference. They are accessed using the enclosing class name. To instantiate an inner class, you must first instantiate the outer class.

Why inner classes Cannot have static declarations?

Quoting another answer, It's because an inner class is implicitly associated with an instance of its outer class, it cannot define any static methods itself.


2 Answers

This is an interesting one. According to [1], the scope of the name "TestClassOne" is "the entire body of" class "TestSuite".

Is the annotation in "the body of" TestSuite? Apparently not. But that's not very fair. The scope rule was defined before annotation was introduced. I don't see any problem if a class annotation is considered in the scope of the class. They are very intimate anyway.

Another question is how come simple name "TestSuite" can be referenced in the annotation? It turns out the spec covers this one. Annotation is a modifier, which is part of the type declaration, and "The scope of a top level type is all type declarations in the package".

However it is possible that the spec got it right by accident. The rules were defined before annotation was introduced, and remain the same afterwards. So although it covers the case in technicality, it could be an accident. This is not to doubt the brain power of language designers - the whole spec is just too damn complex.

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

like image 106
irreputable Avatar answered Sep 28 '22 14:09

irreputable


You don't need to import the inner class, you could access them using

TestSuite.TestClassOne

The details can be found in JLS, but my simple rule is: An import a.b.c.d.e allows you to use e instead of the fully qualified name. It doesn't allow you to use f.

like image 23
maaartinus Avatar answered Sep 28 '22 14:09

maaartinus