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.
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.
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.
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.
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.
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
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With