【问题标题】:Fundamental impediments for non-static access from inner classes to outer interfaces从内部类到外部接口的非静态访问的基本障碍
【发布时间】:2014-01-28 23:02:12
【问题描述】:

例子:

interface Outer {
    default String get() {
        return "hi";
    }
    class Inner {
        String got() {
            return get();
        }
    }
}

这会产生错误

java:不能从静态上下文引用非静态方法 get()。

内部接口/类总是静态的;与外部类不同,除非声明为静态,否则它是非静态的。

这就是今天和即将到来的 java 8 中的情况。外部类和外部接口之间的这种差异是否存在根本原因?

更新: 阅读@Radiodef 的评论后,我将内部接口更改为内部类。外部类不能包含非静态内部接口,因此该示例令人困惑。无论如何,内部类确实是我想要的。

更新:供参考。这是完全合法的:

class Outer {
    String get() {
        return "hei";
    }
    class Inner {
        String got() {
            return get();
        }
    }
}

【问题讨论】:

  • 在 Java 8 之前,我会说这是因为接口不是对象,也不包含数据(不能有非静态成员字段);向接口添加数据会使实现更加复杂,因为接口允许多重继承;并且非静态内部接口必须有一个指向外部对象的指针,即数据。我不知道在 Java 8 中是否仍然如此。
  • 澄清一下,一般来说,您想知道为什么接口不能有内部类? (因为接口也不能有内部类。)普通类也不能有“内部接口”。
  • 在 Java 中,没有什么会强迫您在 Outer 实现中拥有 Inner 实现,因此 Inner 无法了解有关 Outer 的任何信息。
  • @Darkhogg 一个内部类/接口知道外部
  • 非静态内部类实例知道封闭的外部类实例,因为它们带有对它的隐式引用。我怀疑接口可以做到这一点,因为它们不允许包含状态。这也解释了为什么您的代码无法按预期工作 - 没有引用可以调用 get()Outer 实例。

标签: java static java-8


【解决方案1】:

也许我误解了你的问题,但你的代码 sn-p 完全等同于

interface Outer {
    public default String get() {
        return "hi";
    }
    public static class Inner {
        String got() {
            return get();
        }
    }
}

正如the JLS Chapter 9.5 (Java 8) 所说

接口中的成员类型声明隐式为publicstatic。允许冗余指定其中一个或两个 修饰符。

如果你这样做了

Inner innerInstance = new Outer.Inner();
innerInstance.got();

get() 会在什么情况下被调用?这里不涉及Outer 类型的对象。

外部和外部之间的这种差异是否有根本原因? 类和外部接口?

这不是问题。 您的课程代码是inner classes 的示例,即。非static 嵌套类。 接口代码是static 嵌套类的示例。你在比较两个不同的东西。

在封闭类中具有 static 嵌套类的等效示例是

class Outer {
    String get() {
        return "hei";
    }

    public static class Inner {
        String got() {
            return get(); // won't compile
        }
    }
}

get() 再次工作没有意义,因为没有相应的(封闭的)实例来调用它。


如果问题,正如@Radiodef 所说,是

除了 this 之外,为什么类必须是隐式静态的 现有规范?

那么我的回答如下:

根据定义,接口是

独立系统或不同群体相互作用的点

接口没有状态,也没有行为。它只是描述行为。接口成员隐式为static,因为接口没有状态。

【讨论】:

  • 我认为问题不是 “为什么这不起作用?” 而是 “为什么这不起作用?” 或者说换一种说法,“为什么除了这是现有规范之外,该类必须是隐式静态的?”
  • @Radiodef 我的编辑是我能做的最好的回答。
  • 内部类需要持有对外部接口的引用而不是反向。在 Java 8 之前,我可以承认有关接口行为的论点,但对于扩展方法,该论点是多余的。
  • @thoredge 您是否建议 Java 8+ 接口现在应该支持声明static 和非static 嵌套类?
【解决方案2】:

我会提供一种方法让你记住它。

  1. 对于static 成员,它不绑定到声明类/接口的对象;对于非static 成员,它必须绑定到声明类的对象。
  2. 所有接口的成员都是隐式staticdefault 除外。

因此,在您的示例中:static class Inner 未绑定到 interface Outer 的对象(因为 interface 的对象没有意义),所以它不能调用Outer的成员。

更新中您的合法对象:class Inner 绑定到class Outer 的对象,因此当您创建Inner 的对象时,您也创建了@ 的匿名对象987654332@,因此当您在 Inner::got() 中调用 get() 时,会在该匿名对象上调用 get()

希望对您有所帮助。

【讨论】:

  • 它没有帮助。默认方法使用接口对象;在理论上,内部类可能也是如此。当然不是目前,但原则上
  • @thoredge:您能否提供“默认方法使用接口对象”的来源?我目前的想法是默认方法绑定到继承子类对象...
  • 是的;并且以同样的方式内部成员类可以绑定到继承的子类对象。我将您的“接口对象”解释为
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多