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

java interface methods static

97694 观看

14回复

43229 作者的声誉

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

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

上面的代码给出了以下错误(至少在Eclipse中):“接口方法ITest.test()的非法修饰符;只允许使用public和abstract”。

作者: Henrik Paul 的来源 发布者: 2008 年 8 月 22 日

回应 14


7

10465 作者的声誉

静态方法不是实例方法。没有实例上下文,因此从界面实现它没有多大意义。

作者: Ryan Farley 发布者: 2008 年 8 月 22 日

18

59149 作者的声誉

我将以一个例子回答你的问题。假设我们有一个带有静态方法add的Math类。您可以这样调用此方法:

Math.add(2, 3);

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

作者: Kyle Cronin 发布者: 2008 年 8 月 22 日

44

34322 作者的声誉

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

作者: Espo 发布者: 2008 年 8 月 22 日

2

21187 作者的声誉

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

作者: Rob Cooper 发布者: 2008 年 8 月 22 日

-2

114192 作者的声誉

也许代码示例会有所帮助,我将使用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);
}

所以现在你看到界面是如何非常有用的。

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

如果你已经支付了静态费用,那么在通过accountsToPay中的IPayable进行循环时,将无法确定它是否应该在BusinessAcount或CustomerAccount上调用pay。

作者: FlySwat 发布者: 2008 年 8 月 22 日

85

38215 作者的声誉

决定

这里有一些问题在起作用。第一个是在不定义静态方法的情况下声明静态方法的问题。这是两者之间的区别

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

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

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

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

作者: James A. Rosen 发布者: 2008 年 8 月 22 日

11

30956 作者的声誉

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

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

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

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

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

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

作者: Mnementh 发布者: 2008 年 9 月 26 日

4

18110 作者的声誉

有一个很不错的,简洁的回答你的问题在这里。(这让我感到非常直截了当地解释它,我想从这里链接它。)

作者: Zarkonnen 发布者: 2009 年 2 月 6 日

3

6344 作者的声誉

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

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

相同的技术也可用于注释:

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();
        }
    }
}

应始终以Interface.fn...代替的形式访问内部类Class.fn...,然后,您可以摆脱模糊的问题。

作者: Xiè Jìléi 发布者: 2013 年 9 月 17 日

0

129 作者的声誉

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

如果类的成员声明为static,则可以将其与其类名一起使用,该类名仅限于该类,而不创建对象。

如果一个类的成员被声明为abstract,则需要将该类声明为abstract,并且需要在其继承的类(Sub-Class)中提供抽象成员的实现。

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

作者: Sankar 发布者: 2013 年 10 月 2 日

0

182 作者的声誉

由于静态方法无法继承。所以没有必要将它放在界面中。接口基本上是一个所有订户都必须遵循的合同。在接口中放置静态方法将强制订户实现它。现在,与静态方法无法继承的事实相矛盾。

作者: ip_x 发布者: 2013 年 12 月 15 日

5

185 作者的声誉

现在,Java8允许我们在接口中定义甚至静态方法。

interface X {
    static void foo() {
       System.out.println("foo");
    }
}

class Y implements X {
    //...
}

public class Z {
   public static void main(String[] args) {
      X.foo();
      // Y.foo(); // won't compile because foo() is a Static Method of X and not Y
   }
}

注意:如果我们没有明确地使用关键字default / static来使它们成为默认方法和静态方法,则默认情况下,接口中的方法仍然是公共抽象。

作者: Anandaraja_Srinivasan 发布者: 2014 年 3 月 28 日

1

1408 作者的声誉

Java 8改变了世界,你可以在界面中拥有静态方法,但它会强制你为它提供实现。

public interface StaticMethodInterface {
public static int testStaticMethod() {
    return 0;
}

/**
 * Illegal combination of modifiers for the interface method
 * testStaticMethod; only one of abstract, default, or static permitted
 * 
 * @param i
 * @return
 */
// public static abstract int testStaticMethod(float i);

default int testNonStaticMethod() {
    return 1;
}

/**
 * Without implementation.
 * 
 * @param i
 * @return
 */
int testNonStaticMethod(float i);

}

作者: Kumar Abhishek 发布者: 2016 年 2 月 5 日

0

4 作者的声誉

使用Java 8,接口现在可以使用静态方法。

例如,Comparator有一个静态的naturalOrder()方法。

接口无法实现的要求也已经放宽。接口现在可以声明“默认”方法实现,这类似于普通实现,但有一个例外:如果从接口继承默认实现和从超类继承普通实现,则超类的实现将始终优先。

作者: Ishara 发布者: 2019 年 2 月 21 日
32x32