java编译器奇怪:在同一个类中声明的字段,但"不可见"

mer*_*ike 7 java compiler-construction generics compiler-errors

eclipse编译器拒绝编译以下代码,声明字段s不可见.(IBM的Aspect J编译器也拒绝,说"无法解决")为什么会这样?

public class Test {

    String s;

    void foo(Object o) {
        String os = getClass().cast(o).s;
    }
}
Run Code Online (Sandbox Code Playgroud)

Java语言规范声明:

否则,我们说存在默认访问权限,只有在声明类型的包中发生访问时才允许访问.

我理解它的方式,该字段在同一个编译单元中声明和访问,因此在同一个包中,因此应该是可访问的.

更奇怪的是,从增加一个垂头丧气? extends Test,以Test使现场可见,即下面的代码编译:

public class Test {

    String s;

    void foo(Object o) {
        Test t = getClass().cast(o);
        String os = t.s;
    }
}
Run Code Online (Sandbox Code Playgroud)

我偶然发现了编译器错误,或者误解了Java规范吗?

编辑: 我现在在另一台电脑上.在这里,javac接受代码,但eclipse仍然没有.这台机器上的版本:

Eclipse平台

版本:3.4.2构建ID:M20090211-1700

JDK 1.6.0

编辑2 确实,javac接受了代码.我通过运行ant build来测试,它使用了IBM的Ascpect J编译器......

alp*_*ero 6

试试这个:

void foo(Object o) {
    Test foo = getClass().cast(o);
    String so = foo.s;
}
Run Code Online (Sandbox Code Playgroud)

[编辑澄清]:

getClass().cast(o)返回类型为' capture#1-of? extends Test' 的对象而不是Test.所以这个问题与泛型以及编译器如何处理它有关.我不知道泛型规范的细节,但鉴于一些编译器(这里的评论)确实接受了你的代码,那么这可能是规范中的一个循环漏洞,或者这些编译器中的一些并不完全符合规范.

[最后的想法]:我相信eclipse编译器实际上(小心)正确.该对象o实际上可能是Test的扩展(并在另一个包中定义),并且编译器无法知道是否确实如此.所以它将它视为另一个包中定义的扩展实例的最坏情况.如果向final类添加限定符Test将允许访问字段s,那将是非常正确的,但事实并非如此.