为什么接口中没有静态方法,但静态字段和内部类可以?[Java8 之前的]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/129267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:38:59  来源:igfitidea点击:

Why no static methods in Interfaces, but static fields and inner classes OK? [pre-Java8]

javainterfacejls

提问by skaffman

There have been a few questions asked here about why you can't define static methods within interfaces, but none of them address a basic inconsistency: why can you define static fields and static inner types within an interface, but not static methods?

这里有一些关于为什么不能在接口中定义静态方法的问题,但没有一个解决基本的不一致问题:为什么可以在接口中定义静态字段和静态内部类型,而不能定义静态方法?

Static inner types perhaps aren't a fair comparison, since that's just syntactic sugar that generates a new class, but why fields but not methods?

静态内部类型可能不是一个公平的比较,因为这只是生成新类的语法糖,但为什么是字段而不是方法?

An argument against static methods within interfaces is that it breaks the virtual table resolution strategy used by the JVM, but shouldn't that apply equally to static fields, i.e. the compiler can just inline it?

反对接口中的静态方法的一个论点是它破坏了 JVM 使用的虚拟表解析策略,但这不应该同样适用于静态字段,即编译器可以内联它吗?

Consistency is what I desire, and Java should have either supported no statics of any form within an interface, or it should be consistent and allow them.

一致性是我想要的,Java 应该要么不支持接口内任何形式的静态,要么应该保持一致并允许它们。

采纳答案by erickson

An official proposalhas been made to allow static methods in interfaces in Java 7. This proposal is being made under Project Coin.

已经提出了在 Java 7 接口中允许静态方法的官方提案。该提案是在Project Coin下提出的。

My personal opinion is that it's a great idea. There is no technical difficulty in implementation, and it's a very logical, reasonable thing to do. There are several proposals in Project Coin that I hope will neverbecome part of the Java language, but this is one that could clean up a lot of APIs. For example, the Collectionsclass has static methodsfor manipulating any Listimplementation; those could be included in the Listinterface.

我个人的意见是,这是个好主意。实现上没有技术难度,做起来很合乎逻辑,合情合理。Project Coin 中有几项提案,我希望它们永远不会成为 Java 语言的一部分,但这是一项可以清理大量 API 的提案。例如,Collections该类具有用于操作任何List实现的静态方法;这些可以包含在List界面中。



Update:In the Java Posse Podcast #234,Joe D'arcy mentioned the proposal briefly, saying that it was "complex" and probably would not make it in under Project Coin.

更新:Java Posse Podcast #234 中,Joe D'arcy 简短地提到了该提案,称其“复杂”,可能无法在 Project Coin 下进行。



Update:While they didn't make it into Project Coin for Java 7, Java 8 does support static functions in interfaces.

更新:虽然他们没有进入 Java 7 的 Project Coin,但 Java 8 确实支持接口中的静态函数。

回答by Eli Courtwright

Two main reasons spring to mind:

想到两个主要原因:

  1. Static methods in Java cannot be overridden by subclasses, and this is a much bigger deal for methods than static fields. In practice, I've never even wanted to override a field in a subclass, but I override methods all the time. So having static methods prevents a class implementing the interface from supplying its own implementation of that method, which largely defeats the purpose of using an interface.

  2. Interfaces aren't supposed to have code; that's what abstract classes are for. The whole point of an interface is to let you talk about possibly-unrelated objects which happen to all have a certain set of methods. Actually providing an implementation of those methods is outside the bounds of what interfaces are intended to be.

  1. Java 中的静态方法不能被子类覆盖,这对于方法来说比静态字段要大得多。在实践中,我什至从未想覆盖子类中的字段,但我一直覆盖方法。因此,使用静态方法可以防止实现接口的类提供自己的方法实现,这在很大程度上违背了使用接口的目的。

  2. 接口不应该有代码;这就是抽象类的用途。接口的全部意义在于让您谈论可能不相关的对象,这些对象碰巧都有一组特定的方法。实际上提供这些方法的实现超出了接口的意图。

回答by cynicalman

Only static final fields may be declared in an interface (much like methods, which are public even if you don't include the "public" keyword, static fields are "final" with or without the keyword).

在接口中只能声明静态 final 字段(很像方法,即使您不包含“public”关键字,这些方法也是公开的,静态字段无论是否带有关键字都是“final”)。

These are only values, and will be copied literally wherever they are used at compile time, so you never actually "call" static fields at runtime. Having a static method would not have the same semantics, since it would involve calling an interface without an implementation, which Java does not allow.

这些只是值,并且会在编译时使用它们的地方逐字复制,因此您永远不会在运行时实际“调用”静态字段。拥有静态方法不会有相同的语义,因为它会涉及调用没有实现的接口,这是 Java 不允许的。

回答by DJClayworth

There is never a point to declaring a static method in an interface. They cannot be executed by the normal call MyInterface.staticMethod(). (EDIT:Since that last sentence confused some people, calling MyClass.staticMethod() executes precisely the implementation of staticMethod on MyClass, which if MyClass is an interface cannot exist!) If you call them by specifying the implementing class MyImplementor.staticMethod() then you must know the actual class, so it is irrelevant whether the interface contains it or not.

在接口中声明静态方法从来没有意义。它们不能通过正常调用 MyInterface.staticMethod() 来执行。(编辑:由于最后一句话混淆了一些人,调用 MyClass.staticMethod() 正是在 MyClass 上执行 staticMethod 的实现,如果 MyClass 是接口,则不存在!)如果您通过指定实现类 MyImplementor.staticMethod() 调用它们那么你必须知道实际的类,所以接口是否包含它无关紧要。

More importantly, static methods are never overridden, and if you try to do:

更重要的是,静态方法永远不会被覆盖,如果您尝试这样做:

MyInterface var = new MyImplementingClass();
var.staticMethod();

the rules for static say that the method defined in the declared type of var must be executed. Since this is an interface, this is impossible.

static 的规则说必须执行在 var 声明类型中定义的方法。由于这是一个接口,这是不可能的。

You can of course always remove the static keyword from the method. Everything will work fine. You may have to suppress some warnings if it is called from an instance method.

您当然可以始终从方法中删除 static 关键字。一切都会好起来的。如果从实例方法调用它,您可能必须抑制一些警告。

To answer some of the comments below, the reason you can't execute "result=MyInterface.staticMethod()" is that it would have to execute the version of the method defined in MyInterface. But there can't be a version defined in MyInterface, because it's an interface. It doesn't have code by definition.

为了回答下面的一些评论,您不能执行“result=MyInterface.staticMethod()”的原因是它必须执行在 MyInterface 中定义的方法的版本。但是不能在 MyInterface 中定义版本,因为它是一个接口。根据定义,它没有代码。

回答by toolkit

Prior to Java 5, a common usage for static fields was:

在 Java 5 之前,静态字段的常见用法是:

interface HtmlConstants {
    static String OPEN = "<";
    static String SLASH_OPEN = "</";
    static String CLOSE = ">";
    static String SLASH_CLOSE = " />";
    static String HTML = "html";
    static String BODY = "body";
    ...
}

public class HtmlBuilder implements HtmlConstants { // implements ?!?
    public String buildHtml() {
       StringBuffer sb = new StringBuffer();
       sb.append(OPEN).append(HTML).append(CLOSE);
       sb.append(OPEN).append(BODY).append(CLOSE);
       ...
       sb.append(SLASH_OPEN).append(BODY).append(CLOSE);
       sb.append(SLASH_OPEN).append(HTML).append(CLOSE);
       return sb.toString();
    }
}

This meant HtmlBuilderwould not have to qualify each constant, so it could use OPENinstead of HtmlConstants.OPEN

这意味着HtmlBuilder不必限定每个常量,因此它可以使用OPEN而不是HtmlConstants.OPEN

Using implements in this way is ultimately confusing.

以这种方式使用工具最终会令人困惑。

Now with Java 5, we have the import staticsyntax to achieve the same effect:

现在在 Java 5 中,我们有import 静态语法来实现相同的效果:

private final class HtmlConstants {
    ...
    private HtmlConstants() { /* empty */ }
}

import static HtmlConstants.*;
public class HtmlBuilder { // no longer uses implements
    ...
}

回答by Alexander

The purpose of interfaces is to define a contract without providing an implementation. Therefore, you can't have static methods, because they'd have to have an implementation already in the interface since you can't override static methods. As to fields, only static final fieldsare allowed, which are, essentially, constants (in 1.5+ you can also have enums in interfaces). The constants are there to help define the interface without magic numbers.

接口的目的是在不提供实现的情况下定义契约。因此,您不能拥有静态方法,因为它们必须在接口中已经有一个实现,因为您无法覆盖静态方法。至于字段,只final fields允许静态,本质上是常量(在 1.5+ 中,您也可以在接口中使用枚举)。常量用于帮助定义没有幻数的接口。

BTW, there's no need to explicitly specify static finalmodifiers for fields in interfaces, because only static final fields are allowed.

顺便说一句,没有必要为static final接口中的字段显式指定修饰符,因为只允许静态最终字段。

回答by skaffman

I'm going to go with my pet theory with this one, which is that the lack of consistency in this case is a matter of convenience rather than design or necessity, since I've heard no convincing argument that it was either of those two.

我将继续我的宠物理论,即在这种情况下缺乏一致性是一个方便的问题,而不是设计或必要性,因为我没有听到令人信服的论点,即它是这两者中的任何一个.

Static fields are there (a) because they were there in JDK 1.0, and many dodgy decisions were made in JDK 1.0, and (b) static final fields in interfaces are the closest thing java had to constants at the time.

静态字段存在(a)因为它们在 JDK 1.0 中存在,并且在 JDK 1.0 中做出了许多狡猾的决定,并且(b)接口中的静态最终字段是当时 java 最接近常量的东西。

Static inner classes in interfaces were allowed because that's pure syntactic sugar - the inner class isn't actually anything to do with the parent class.

接口中的静态内部类是允许的,因为那是纯粹的语法糖 - 内部类实际上与父类没有任何关系。

So static methods aren't allowed simply because there's no compelling reason to do so; consistency isn't sufficiently compelling to change the status quo.

所以不允许静态方法仅仅因为没有令人信服的理由这样做;一致性不足以改变现状。

Of course, this could be permitted in future JLS versions without breaking anything.

当然,这可以在未来的 JLS 版本中被允许而不会破坏任何东西。

回答by skaffman

Actually sometimes there are reasons someone can benefit from static methods. They can be used as factory methods for the classes that implement the interface. For example that's the reason we have Collection interface and the Collections class in openjdk now. So there are workarounds as always - provide another class with a private constructor which will serve as a "namespace" for the static methods.

实际上,有时有人可以从静态方法中受益是有原因的。它们可以用作实现接口的类的工厂方法。例如,这就是我们现在在 openjdk 中有 Collection 接口和 Collections 类的原因。因此,一如既往地有变通方法 - 提供另一个具有私有构造函数的类,该构造函数将用作静态方法的“命名空间”。

回答by laz

The reason is that all methods defined in an interface are abstract whether or not you explicitly declare that modifier. An abstract static method is not an allowable combination of modifiers since static methods are not able to be overridden.

原因是接口中定义的所有方法都是抽象的,无论您是否明确声明该修饰符。抽象静态方法不是修饰符的允许组合,因为静态方法不能被覆盖。

As to why interfaces allow static fields. I have a feeling that should be considered a "feature". The only possibility I can think of would be to group constants that implementations of the interface would be interested in.

至于为什么接口允许静态字段。我有一种感觉,应该被视为“功能”。我能想到的唯一可能性是将接口的实现感兴趣的常量分组。

I agree that consistency would have been a better approach. No static members should be allowed in an interface.

我同意一致性会是更好的方法。接口中不应允许静态成员。

回答by MetroidFan2002

Static methods are tied to a class. In Java, an interface is not technically a class, it is a type, but not a class (hence, the keyword implements, and interfaces do not extend Object). Because interfaces are not classes, they cannot have static methods, because there is no actual class to attach to.

静态方法绑定到一个类。在 Java 中,接口在技术上不是一个类,它是一个类型,但不是一个类(因此,关键字实现,接口不扩展 Object)。因为接口不是类,所以它们不能有静态方法,因为没有实际的类可以附加。

You may call InterfaceName.class to get the Class Object corresponding to the interface, but the Class class specifically states that it represents classes and interfaces in a Java application. However, the interface itself is not treated as a class, and hence you cannot attach a static method.

您可以调用InterfaceName.class 来获取接口对应的Class Object,但是Class 类特别声明它代表Java 应用程序中的类和接口。但是,接口本身不被视为类,因此您不能附加静态方法。