【问题标题】:Javac fails with "attempting to assign weaker access privileges" on intersection typeJavac 在交集类型上“尝试分配较弱的访问权限”失败
【发布时间】:2019-02-28 01:53:02
【问题描述】:

考虑这个 Java 程序:

public class IntersectionBug {

    public static interface FooInterface {
        public void foo();
    }

    public static class FooSupport {
        protected void foo() {
        }
    }

    public static class Whatever<T extends FooSupport & FooInterface> {
    }
}

在JDK 1.8编译器下编译失败:

$ javac IntersectionBug.java
IntersectionBug.java:12: error: foo() in FooSupport cannot implement foo() in FooInterface
    public static class Whatever<T extends FooSupport & FooInterface> {
                                 ^
  attempting to assign weaker access privileges; was public
1 error

显然,如果某个类型 T 既是 FooSupport 又是 FooInterface,那么它必须有 public void foo(),所以错误是假的。

我的问题:这是编译器错误,还是 JLS 真的指定该程序无效?如果是后者,为什么这里的 JLS 行为是次优的?

【问题讨论】:

    标签: javac jls


    【解决方案1】:

    JLS §4.9 通过概念类的概念定义交集类型及其成员。在您的特定情况下,名义类是:

    class <notional> extends FooSupport implements FooInterface {}
    

    请注意空的类主体。

    JLS 段落旨在暗示概念类必须是格式良好的,否则会发生编译错误。显然,继承公共接口方法的受保护实现的类的格式不正确。

    我同意可能有其他方法来指定一个交集类型,允许 FooSupport 的未知子类通过覆盖具有公共可见性的方法来解决上述冲突。

    我相信选择通过概念类进行定义的风格是为了避免复杂性。看看 §4.9 与其他定义相比有多简洁。

    PS:ecj 也拒绝了你的例子,说:

    继承的方法IntersectionBug.FooSupport.foo()不能隐藏IntersectionBug.FooInterface中的公共抽象方法

    【讨论】:

    • this answer 中,Brian Goetz 在相关的问答中证实,将名义类型与实际类型一样的处理是一个错误,即使是由规范本身引起的。除此之外,javac 正在向the old one 堆积更多问题,例如this newer one...
    • 感谢@Holger 提供有趣的链接。通常,当实现违反规范时,我会保留术语“错误”,但布赖恩肯定是少数能够将规范归类为有缺陷的人之一 :) - 鉴于多年来我们在 JDK 错误中没有看到很多动作,那么更改一个编译器 (ecj) 以符合假设的、预期的、未成文的规范是否有意义?还是我们应该接受 Java(由 JLS、java、ecj 实现)不是它想要成为的语言这一事实​​?
    • 好吧,我无法决定这个。但我认为 ECJ 团队和 javac 团队之间就此类未解决的问题进行了一些沟通?所以也许你可以给他们一些压力?根据我的经验,只要没有人对问题施加压力,JDK 错误可以在列表中停留任意长时间。除此之外,我想指出一个事实,there is already a deviation 以及,我不确定我是否可以从规范中读到“概念类型”必须根据继承规则进行检查。
    • @Holger 是的,ECJ 团队和 javac 团队以及 JLS 作者之间存在沟通。但是,我更愿意将这种交流限制在技术讨论中,而不是试图施加压力。在同一个频道上做这两个似乎效果不佳。我只是希望“社区”对甲骨文更加直言不讳,要求解决那些未解决的问题。目前正在bugs.openjdk.java.net/browse/JDK-8215739
    • 不要太从字面上理解“施加压力”。开始讨论将是一个好的开始。 “社区”的问题是他们根本无法为列表中的现有错误做出贡献;只有注册开发者才能做到这一点,成为拥有必要权限的注册开发者并不容易。普通开发人员所能做的就是开始一个新的错误报告at this place 并无助地观察进展(或缺乏进展)......
    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    相关资源
    最近更新 更多