【问题标题】:Why are interfaces static?为什么接口是静态的?
【发布时间】:2023-04-04 16:29:01
【问题描述】:

为什么我不能在内部类中拥有接口?为什么它们天生就是static?对不起,如果这是一个愚蠢的问题,我已经尽我所能一次又一次地用谷歌搜索,但我似乎无法把它包裹在我的头上。至于为什么我不能在内部类/本地类中声明这些?

同样作为确认,我们可以在接口中使用静态最终变量的原因是因为它们没有指定状态或任何此类实现,对吗?如果我们丢失了static 并且只使用了一个final,我们需要一个没有意义的实例,因为你不能实例化一个接口。抱歉,我真的很困惑,我知道我应该再提一个问题,但我认为这两个问题有些相关。

【问题讨论】:

    标签: java class interface static local


    【解决方案1】:

    为什么内部类中不能有接口?

    因为接口是隐式静态的:JLS §8.5.1:

    成员接口是隐式静态的(第 9.1.1 节)。允许成员接口的声明冗余指定静态修饰符。

    并且你不能在内部类中拥有非最终静态变量。

    为什么它们是隐式静态的?

    因为他们就是这样设计的。

    为什么我不能在内部类/本地类中声明这些?

    因为它们是隐式静态的。

    我们可以在接口中使用静态最终变量的原因是因为它们没有指定状态或任何此类实现,对吗?

    没错。

    如果我们失去静态而只使用一个final,我们需要一个实例

    没错。

    这没有任何意义,因为您无法实例化接口。

    是的,你可以。您可以实例化一个实现接口的类,也可以实例化它的方法本地匿名实现。这里真正的问题是接口的多重继承。

    【讨论】:

    • 想了想,我猜想答案是“为什么我不能在内部类/本地类中声明这些?”也应该是“因为这是他们设计的方式”,至少对于命名的内部类。名称空间在编译时就存在,因此似乎没有技术理由禁止它。现在没有命名空间的本地类可能会更成问题,没有好的方法来引用它们。
    【解决方案2】:

    想想 static 的含义 - “与特定实例无关”。因此,正如您所指出的,Foo 类的 static 字段不属于任何 Foo 实例,而是属于 Foo 本身。

    现在想想什么是接口——它是一个契约,一个实现它的类承诺提供的方法列表。另一种思考方式是,接口是一组“与特定类无关”的方法——任何类都可以实现它,只要它提供这些方法。

    所以,如果一个接口与任何特定的类无关,那么很明显,一个接口不可能与一个类的 instance 相关 - 对吧?

    *注意,正如@Owlstead 指出的那样,有一些方法可以在类中定义接口。但是,为了让您了解接口是什么(这似乎是您正在处理的工作),我现在会忽略这些可能性,因为它们会分散并可能掩盖接口的一般用途。

    【讨论】:

    • 此外,我想说的是 OP 使用术语 static 来引用 Java Interface 是不正确/不准确的。接口是一种顶级语言结构,但它们不是“静态”的,方法或字段可以声明为static
    • 是的,我完全同意在类中使用接口——更不用说嵌套类——不应该经常使用的观点。
    • @drewmoore 删除了那个答案,如果你想处理嵌套类,你可能希望将它们包含在你的答案中。
    • @aroth JLS 8.5.1:“成员接口是隐式静态的(第 9.1.1 节)。允许成员接口的声明冗余地指定静态修饰符。”。
    【解决方案3】:

    您不能在内部类中拥有接口,因为内部类仅存在于“外部类”实例的上下文中。既然是这种情况,您的界面实际上是非静态的。

    但是,您可以在嵌套类中拥有一个接口。请参阅@owlstead 答案。通过将“静态”关键字放在“内部类”的声明中,它成为一等公民,可从外部类外部引用,并且(大部分)独立于外部类的上下文。嵌套类可以在外部类之外实例化;内部类不能。

    【讨论】:

    • “将 'static' 关键字放在“内部类”的声明上”在术语上是矛盾的。你的意思是“嵌套类”。
    【解决方案4】:

    为什么它们[接口]本质上是static

    static 和非static 嵌套类之间的区别在于它们的实例是否隐式引用了(包含类的)封闭实例,以及局部变量从包含范围。在 Java 8 之前,接口无法使用此类隐式引用,因为接口无法初始化任何非静态字段或提供任何方法实现。 (它仍然无法初始化非静态字段,尽管现在它可以提供 default 方法实现。)所以在 Java 8 之前,非static 嵌套接口没有任何意义。

    此外,从实现的角度来看,这些隐式引用被实现为内部类上的额外字段,并且它们还需要内部类构造函数的额外参数(以初始化这些字段)。接口没有字段或构造函数,因此无法实现。

    (注意:我通常不建议尝试从实现的角度来理解语言设计决策,因为单一语言功能可以有许多不同的正确实现。但我认为这是理解实现有助于理解的一种情况规范,因此是上一段。)

    【讨论】:

    • 恕我直言,这个答案是唯一真正回答问题的答案;长话短说,在 Java 8 非静态接口没有意义之前,为了向后兼容,Java 8 和更新版本仍然是这种情况。很好的答案,@ruakh
    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 2011-01-26
    • 2012-05-27
    • 1970-01-01
    • 2018-01-28
    • 2012-06-05
    相关资源
    最近更新 更多