Java 为什么我不能在接口中声明静态方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21817/
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 07:14:28  来源:igfitidea点击:

Why can't I declare static methods in an interface?

javainterfacemethodsstatic

提问by Henrik Paul

The topic says the most of it - what is the reason for the fact that static methods can't be declared in an interface?

该主题说明了大部分内容 - 无法在接口中声明静态方法的原因是什么?

public interface ITest {
    public static String test();
}

The code above gives me the following error (in Eclipse, at least): "Illegal modifier for the interface method ITest.test(); only public & abstract are permitted".

上面的代码给了我以下错误(至少在 Eclipse 中):“接口方法 ITest.test() 的非法修饰符;只允许公共和抽象”。

采纳答案by James A. Rosen

There are a few issues at play here. The first is the issue of declaring a static method without defining it. This is the difference between

这里有几个问题在起作用。第一个是声明一个静态方法而不定义它的问题。这是之间的区别

public interface Foo {
  public static int bar();
}

and

public interface Foo {
  public static int bar() {
    ...
  }
}

The first is impossible for the reasons that Espomentions: you don't know which implementing class is the correct definition.

由于Espo提到的原因,第一个是不可能的:您不知道哪个实现类是正确的定义。

Java couldallow the latter; and in fact, starting in Java 8, it does!

Java可以允许后者;事实上,从 Java 8 开始,它确实如此!

回答by Ryan Farley

Static methods are not instance methods. There's no instance context, therefore to implement it from the interface makes little sense.

静态方法不是实例方法。没有实例上下文,因此从接口实现它几乎没有意义。

回答by Kyle Cronin

I'll answer your question with an example. Suppose we had a Math class with a static method add. You would call this method like so:

我会用一个例子来回答你的问题。假设我们有一个带有静态方法 add 的 Math 类。你会像这样调用这个方法:

Math.add(2, 3);

If Math were an interface instead of a class, it could not have any defined functions. As such, saying something like Math.add(2, 3) makes no sense.

如果 Math 是一个接口而不是一个类,它就不能有任何定义的函数。因此,说像 Math.add(2, 3) 这样的东西是没有意义的。

回答by Espo

The reason why you can't have a static method in an interface lies in the way Java resolves static references. Java will not bother looking for an instance of a class when attempting to execute a static method. This is because static methods are not instance dependent and hence can be executed straight from the class file. Given that all methods in an interface are abstract, the VM would have to look for a particular implementation of the interface in order to find the code behind the static method so that it could be executed. This then contradicts how static method resolution works and would introduce an inconsistency into the language.

接口中不能有静态方法的原因在于 Java 解析静态引用的方式。在尝试执行静态方法时,Java 不会费心寻找类的实例。这是因为静态方法不依赖于实例,因此可以直接从类文件中执行。鉴于接口中的所有方法都是抽象的,VM 必须寻找接口的特定实现才能找到静态方法背后的代码,以便它可以被执行。这与静态方法解析的工作方式相矛盾,并且会在语言中引入不一致。

回答by Rob Cooper

An interface is used for polymorphism, which applies to Objects, not types. Therefore (as already noted) it makes no sense to have an static interface member.

接口用于多态,它适用于对象,而不是类型。因此(如前所述)拥有静态接口成员毫无意义。

回答by FlySwat

Perhaps a code example would help, I'm going to use C#, but you should be able to follow along.

也许代码示例会有所帮助,我将使用 C#,但您应该能够继续学习。

Lets pretend we have an interface called IPayable

让我们假设我们有一个名为 IPayable 的接口

public interface IPayable
{
    public Pay(double amount);
}

Now, we have two concrete classes that implement this interface:

现在,我们有两个具体的类来实现这个接口:

public class BusinessAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

public class CustomerAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

Now, lets pretend we have a collection of various accounts, to do this we will use a generic list of the type IPayable

现在,假设我们有各种帐户的集合,为此我们将使用 IPayable 类型的通用列表

List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());

Now, we want to pay $50.00 to all those accounts:

现在,我们要向所有这些帐户支付 50.00 美元:

foreach (IPayable account in accountsToPay)
{
    account.Pay(50.00);
}

So now you see how interfaces are incredibly useful.

所以现在你看到了接口是如何非常有用的。

They are used on instantiated objects only. Not on static classes.

它们仅用于实例化对象。不在静态类上。

If you had made pay static, when looping through the IPayable's in accountsToPay there would be no way to figure out if it should call pay on BusinessAcount or CustomerAccount.

如果您已将 pay 设为静态,则在循环访问 accountsToPay 中的 IPayable 时,将无法确定它是否应在 BusinessAcount 或 CustomerAccount 上调用 pay。

回答by Mnementh

The reason lies in the design-principle, that java does not allow multiple inheritance. The problem with multiple inheritance can be illustrated by the following example:

原因在于设计原则,java 不允许多重继承。下面的例子可以说明多重继承的问题:

public class A {
   public method x() {...}
}
public class B {
   public method x() {...}
}
public class C extends A, B { ... }

Now what happens if you call C.x()? Will be A.x() or B.x() executed? Every language with multiple inheritance has to solve this problem.

现在如果你调用 Cx() 会发生什么?会执行 Ax() 或 Bx() 吗?每种具有多重继承的语言都必​​须解决这个问题。

Interfaces allow in Java some sort of restricted multiple inheritance. To avoid the problem above, they are not allowed to have methods. If we look at the same problem with interfaces and static methods:

Java 中的接口允许某种受限的多重继承。为了避免上面的问题,他们不允许有方法。如果我们看一下接口和静态方法的相同问题:

public interface A {
   public static method x() {...}
}
public interface B {
   public static method x() {...}
}
public class C implements A, B { ... }

Same problem here, what happen if you call C.x()?

同样的问题,如果你调用 Cx() 会发生什么?

回答by Zarkonnen

There's a very nice and concise answer to your question here. (It struck me as such a nicely straightforward way of explaining it that I want to link it from here.)

你的问题在这里有一个非常好的和简洁的答案。(它让我觉得解释它的方式非常简单,我想从这里链接它。)

回答by Xiè Jìléi

It seems the static method in the interface might be supported in Java 8, well, my solution is just define them in the inner class.

似乎Java 8可能支持接口中的静态方法,好吧,我的解决方案只是在内部类中定义它们。

interface Foo {
    // ...
    class fn {
        public static void func1(...) {
            // ...
        }
    }
}

The same technique can also be used in annotations:

同样的技术也可以用在注解中:

public @interface Foo {
    String value();

    class fn {
        public static String getValue(Object obj) {
            Foo foo = obj.getClass().getAnnotation(Foo.class);
            return foo == null ? null : foo.value();
        }
    }
}

The inner class should always be accessed in the form of Interface.fn...instead of Class.fn..., then, you can get rid of ambiguous problem.

内部类应该总是以Interface.fn...而不是的形式访问Class.fn...,这样,你就可以摆脱模棱两可的问题。

回答by Sankar

Illegal combination of modifiers : static and abstract

修饰符的非法组合:静态和抽象

If a member of a class is declared as static, it can be used with its class name which is confined to that class, without creating an object.

如果一个类的成员被声明为静态的,它可以使用其仅限于该类的类名,而无需创建对象。

If a member of a class is declared as abstract, you need to declare the class as abstract and you need to provide the implementation of the abstract member in its inherited class (Sub-Class).

如果类的成员声明为抽象类,则需要将该类声明为抽象类,并且需要在其继承的类(子类)中提供抽象成员的实现。

You need to provide an implementation to the abstract member of a class in sub-class where you are going to change the behaviour of static method, also declared as abstract which is a confined to the base class, which is not correct

您需要为子类中的类的抽象成员提供一个实现,您将在其中更改静态方法的行为,也声明为抽象,它仅限于基类,这是不正确的