关于java:为什么实现类不能将重写方法定义为static?

Why can't implementing classes define an overriding method as static?

我很困惑为什么不允许以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
public interface MyInterface {
  MyInterface getInstance(String name);
}

public class MyImplementation implements MyInterface {
  public MyImplementation(String name) {
  }
  @Override
  public static MyInterface getInstance(String name) { // static is not allowed here
    return new MyImplementation(name)
  }
}

我理解为什么接口中的方法不能是静态的,但是为什么重写方法不能是静态的?

我希望所有类都实现getInstance(String name)方法,但是目前我只限于在对象已经被实例化的情况下调用该方法,哪种方法会破坏目标…

*更新:*谢谢你的回答,我现在更理解了。基本上,我不应该试图让一个实用程序类(或者工厂类)实现一个接口(或者至少,不是这样的)。


调用Java中的静态方法需要指定确切的类型。不可能以多态方式调用静态方法,从而消除了对@Override的需求。

请注意,这种方法并不是所有语言都通用的:例如,您可以重写Objective-C中的类方法,而Apple的Cocoa框架很好地利用这种机制来定制它们的"工厂"类。然而,在爪哇中,C++和C类类方法不支持多态行为。

从理论上讲,Java设计器可以让您通过EDCOX1、1个方法提供接口方法实现,以防实现不需要从实例访问状态。但是使用一个普通的包装器也很容易实现相同的行为:

1
2
3
4
5
6
7
8
9
10
11
public class MyImplementation implements MyInterface {
    public MyImplementation(String name) {
    }
    @Override
    public MyInterface getInstance() { // static is not allowed here
        return getInstanceImpl();
    }
    public static getInstanceImpl() {
        return new MyImplementation(name)
    }
}

Java编译器可以为你做同样的事情,但是看到一个静态方法实现一个实例方法是既不寻常又令人困惑的,所以我猜想Java设计者决定不提供这个"魔术"。


静态方法不能受制于多态行为。那没什么意义。想象一下这个用例,假设您想要的是可能的:

1
2
3
public void foo(MyInterface i) {
    i.getInstance("abc");
}

现在我想用MyInterface的实现(class A来调用这个方法,但是由于我不能传递类本身,所以需要传递一个对象:

1
2
A a = new A();
foo(a);

现在在foo内部,对getInstancestatic重写被类A的实例调用。所以现在我只能创建一个对象来调用静态方法。

我的观点是,在大多数多态性的用例中,您仍然需要被约束来创建一个对象,因为在最初的接口中,该方法是一个实例方法。


答案归结为实现接口意味着什么。当一个类实现一个接口时,这意味着该类的每个实例都将响应接口中的每个方法。当您将该方法实现为静态方法时,可以在没有类实例的情况下调用该方法,但这并不能实现继承实现的承诺,即该方法可以在类的每个实例上调用。


因为实现接口会使实现者成为接口的类型。这意味着实例需要有由类型定义的方法,而不是实例的类。

换一种说法,

public void mymethod

public static void mymethod

不是相同的方法声明。它们是完全不同的。如果在接口上定义了mymethod,那么第二个定义就不能满足实现接口的要求。