java编译器奇怪: field declared in same class,但 "not visible"

标签 java generics compiler-construction compiler-errors

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/

相关文章:

java - 如何在 Debug模式下编译? (netbeans, java, maven)

javascript - 将无类型数组编译为 C 的有效方法是什么?

java - mysql 准备语句 : sql query

ios - 如何使用可选的泛型类型创建动态结构

swift - 使用泛型和协议(protocol)作为类型参数的区别,在函数中实现它们的优缺点是什么

c# - 是否可以使用泛型简化我的 dbtype?

java - 多重继承和类对象

java - Spring MVC : redirect user according to browser language

java - 没有到主机的路由 : connect

java - 与 Java 中的@Override 相反的标记