In the code below, I give two main classes – TestWorks, and TestCompilesButFails. I’m not sure I understand the failure – it would appear that the Arrays.asList() expression is being given type “List of AbstractBaseClass”, but why would it ever be correct to give a type here that references a package-local class in another package?
// failing test class
import somepackage.*;
import java.util.Arrays;
public class TestCompilesButFails {
public static void main(String [] args){
// fails here with java.lang.IllegalAccessError:
// tried to access class somepackage.AbstractBaseClass
// from class TestCompilesButFails
for (Object o : Arrays.asList(new ConcreteA(), new ConcreteB())) {
System.out.println(o);
}
}
}
// package-local abstract base class
package somepackage;
abstract class AbstractBaseClass {
public abstract void doSomething();
}
// next two classes - public extenders of abstract base class
package somepackage;
public class ConcreteA extends AbstractBaseClass {
public void doSomething(){
System.out.print("Look, ma!\n");
}
}
package somepackage;
public class ConcreteB extends AbstractBaseClass {
public void doSomething(){
System.out.print("No types!\n");
}
}
// working test
import somepackage.*;
public class TestWorks {
public static void main(String [] args){
new ConcreteA().doSomething();
new ConcreteB().doSomething();
}
}
Because the type inference algorithm specified in the Java Language Specification does not take into account type visibility:
As for why they defined it that way, I suspect it was to avoid making an already quite complex algorithm more complex for the sole purpose of handling rare corner cases. After all, they also write:
Which in your case would be: