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

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

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

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

这里有几个问题。 首先是没有定义静态方法的问题。 这是区别

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

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

第一个是不可能的,因为Espo提到:你不知道哪个实施阶级是正确的定义。

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

在接口中不能有静态方法的原因在于Javaparsing静态引用的方式。 在尝试执行静态方法时,Java不会为寻找类的实例而烦恼。 这是因为静态方法不依赖于实例,因此可以直接从类文件中执行。 鉴于接口中的所有方法都是抽象的,虚拟机将不得不寻找特定的接口实现来查找静态方法后面的代码,以便执行。 这与静态方法parsing的工作原理相矛盾,并且会在语言中引入不一致。

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

 Math.add(2, 3); 

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

原因在于devise原则,即java不允许多重inheritance。 多重inheritance的问题可以通过下面的例子来说明:

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

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

接口允许在Java中进行某种受限制的多inheritance。 为了避免上述问题,他们不允许有方法。 如果我们看接口和静态方法的问题:

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

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

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

现在Java8允许我们在Interface中定义静态方法。

 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来使Defender方法和静态方法resp,那么接口中的方法依然是公共抽象的。

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

一个接口用于多态,它适用于对象,而不是types。 因此(正如已经提到的),拥有静态接口成员是没有意义的。

看起来接口中的静态方法可能在Java 8中得到支持,那么我的解决scheme就是在内部类中定义它们。

 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...的forms被访问,然后,你可以摆脱模棱两可的问题。

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

}

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

如果一个类的成员被声明为静态的,那么它可以和它的类名一起使用,而不用创build一个对象。

如果一个类的成员被声明为抽象的,你需要声明这个类是抽象的,你需要在它的inheritance类(Sub-Class)中提供抽象成员的实现。

你需要提供一个实现给子类中的一个类的抽象成员,在那里你要改变静态方法的行为,也被声明为抽象的,这是一个限于基类,这是不正确的

由于静态方法不能被inheritance。 所以没有把它放在界面中。 接口基本上是所有用户必须遵循的合同。 在界面中放置一个静态方法将强制用户实现它。 这与静态方法不能被inheritance的事实相矛盾。

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

现在,让我们假装我们有各种账户的集合,为此我们将使用IPayabletypes的通用列表

 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上调用付款。