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

时间:2020-03-05 18:41:54  来源:igfitidea点击:

该主题说最多的是为什么不能在接口中声明静态方法的原因是什么?

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

上面的代码给了我以下错误(至少在Eclipse中):"接口方法ITest.test()的非法修饰符;仅允许public&abstract"。

解决方案

回答

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

回答

我将举例说明问题。假设我们有一个带有静态方法add的Math类。我们将这样调用此方法:

Math.add(2, 3);

如果Math是接口而不是类,则它不能具有任何已定义的函数。因此,说Math.add(2,3)之类的东西是没有道理的。

回答

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

回答

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

回答

也许代码示例会有所帮助,我将使用C#,但是我们应该可以继续学习。

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

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

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

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

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

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

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

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

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

因此,现在我们将看到接口如何发挥不可思议的作用。

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

如果我们已经使薪水保持静态,则在遍历IPayable的accountsToPay中时,将无法确定应在BusinessAcount还是CustomerAccount上调用支付。

回答

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

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

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

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

Java可以允许后者。实际上,从Java 8开始,它确实做到了!

回答

原因在于设计原则,即Java不允许多重继承。下例说明了多重继承的问题:

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

现在,如果我们调用C.x()会发生什么?将执行A.x()或者B.x()吗?具有多重继承的每种语言都必须解决此问题。

接口在Java中允许某种受限的多重继承。为避免上述问题,不允许他们使用方法。如果我们在接口和静态方法上看同样的问题:

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

同样的问题在这里,如果我们调用C.x()会发生什么?

回答

在这里,问题有一个非常简洁的答案。 (这让我很惊讶,因为它是一种非常简单的解释方式,我想从这里进行链接。)