为什么我不能在接口中声明静态方法?
该主题说最多的是为什么不能在接口中声明静态方法的原因是什么?
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()会发生什么?
回答
在这里,问题有一个非常简洁的答案。 (这让我很惊讶,因为它是一种非常简单的解释方式,我想从这里进行链接。)