编辑:从Java 8开始,静态方法现在被允许出现在接口中。

下面是例子:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

当然这行不通。但为什么不呢?

其中一个可能的问题是,当你调用:

IXMLizable.newInstanceFromXML(e);

在这种情况下,我认为它应该只调用一个空方法(即{})。所有子类都必须实现静态方法,所以在调用静态方法时它们都没问题。那为什么不可能呢?

编辑:我想我正在寻找比“因为这就是Java”更深刻的答案。

静态方法不能被覆盖是否有特殊的技术原因?也就是说,为什么Java的设计者决定让实例方法可重写,而不是静态方法?

编辑:我的设计的问题是我试图使用接口来执行编码约定。

也就是说,接口的目标有两个:

我希望IXMLizable接口允许我将实现它的类转换为XML元素(使用多态性,工作正常)。 如果有人想创建实现IXMLizable接口的类的新实例,他们总是知道会有一个newInstanceFromXML(Element e)静态构造函数。

除了在界面中添加注释之外,还有其他方法可以确保这一点吗?


当前回答

静态方法不像实例方法那样是虚拟的,所以我猜想Java设计者决定不让它们出现在接口中。

但是您可以将包含静态方法的类放在接口中。你可以试试!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}

其他回答

随着Java 8的出现,现在可以在接口中编写默认方法和静态方法。 docs.oracle / staticMethod

例如:

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

结果:6

提示:调用静态接口方法不需要由任何类实现。当然,这是因为适用于超类中的静态方法的规则同样适用于接口上的静态方法。

First, all language decisions are decisions made by the language creators. There is nothing in the world of software engineering or language defining or compiler / interpreter writing which says that a static method cannot be part of an interface. I've created a couple of languages and written compilers for them -- it's all just sitting down and defining meaningful semantics. I'd argue that the semantics of a static method in an interface are remarkably clear -- even if the compiler has to defer resolution of the method to run-time.

其次,我们使用静态方法意味着有一个包含静态方法的接口模式的正当理由——我不能代表你们,但我经常使用静态方法。

The most likely correct answer is that there was no perceived need, at the time the language was defined, for static methods in interfaces. Java has grown a lot over the years and this is an item that has apparently gained some interest. That it was looked at for Java 7 indicates that its risen to a level of interest that might result in a language change. I, for one, will be happy when I no longer have to instantiate an object just so I can call my non-static getter method to access a static variable in a subclass instance ...

注释编辑:从Java 8开始,静态方法现在被允许出现在接口中。

这是正确的,静态方法自Java 8以来就被允许在接口中,但您的示例仍然不能工作。你不能只是定义一个静态方法:你必须实现它,否则你会得到一个编译错误。

有几个答案讨论了可覆盖静态方法概念的问题。然而,有时你会遇到一种模式,它似乎正是你想要使用的。

例如,我使用对象关系层,该层有值对象,但也有用于操作值对象的命令。由于各种原因,每个值对象类都必须定义一些静态方法,以便框架找到命令实例。例如,要创建一个Person,你可以这样做:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

通过ID加载Person

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

这是相当方便的,但它有它的问题;值得注意的是,静态方法的存在不能在接口中强制执行。接口中可覆盖的静态方法正是我们所需要的,只要它能以某种方式工作。

EJBs solve this problem by having a Home interface; each object knows how to find its Home and the Home contains the "static" methods. This way the "static" methods can be overridden as needed, and you don't clutter up the normal (it's called "Remote") interface with methods that don't apply to an instance of your bean. Just make the normal interface specify a "getHome()" method. Return an instance of the Home object (which could be a singleton, I suppose) and the caller can perform operations that affect all Person objects.

通常这是使用工厂模式完成的

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}