eclipse 编译器拒绝编译以下代码,指出字段 s 不可见。 (IBM 的 Aspect J 编译器也拒绝,声明“无法解析 s”)这是为什么呢?
public class Test {
String s;
void foo(Object o) {
String os = getClass().cast(o).s;
}
}
Java 语言规范指出:
Otherwise, we say there is default access, which is permitted only when the access occurs from within the package in which the type is declared.
按照我的理解,该字段是在同一个编译单元中声明和访问的,因此在同一个包中,因此应该是可访问的。
更奇怪的是,从 添加一个向下转换?将 Test
扩展到 Test
使该字段可见,即编译以下代码:
public class Test {
String s;
void foo(Object o) {
Test t = getClass().cast(o);
String os = t.s;
}
}
我是否偶然发现了编译器错误,或者误解了 Java 规范?
编辑: 我现在在另一台电脑上。在这里,javac 接受代码,但 eclipse 仍然不接受。 native 版本:
Eclipse Platform
Version: 3.4.2 Build id: M20090211-1700
JDK 1.6.0
编辑 2 实际上,javac 接受代码。我已经通过运行 ant build 进行了测试,它使用 IBM 的 Ascpect J 编译器...
最佳答案
试试这个:
void foo(Object o) {
Test foo = getClass().cast(o);
String so = foo.s;
}
[编辑澄清]:
getClass().cast(o)
返回类型为“capture#1-of?扩展 Test
' 而不是 Test
。所以这个问题与泛型以及编译器如何对待它有关。我不知道泛型规范的详细信息,但考虑到某些编译器(根据此处的评论)确实接受您的代码,那么这要么是规范中的漏洞,要么其中一些编译器不完全符合规范。
[最后的想法]:
我相信 eclipse 编译器实际上(仔细地)在这里是正确的。对象 o
实际上可能是 Test 的扩展(并在另一个包中定义),编译器无法知道是否确实如此。因此,它将其视为另一个包中定义的扩展实例的最坏情况。如果向类 Test
添加 final
限定符将允许访问字段 s
,那将是非常正确的,但事实并非如此。
关于java编译器奇怪: field declared in same class,但 "not visible",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1604147/