这是一个例子:
public interface IXMLizable{ static T newInstanceFromXML(Element e); Element toXMLElement(); }
当然这不会奏效。 但为什么不呢?
其中一个可能的问题是,当您致电时会发生什么:
IXMLizable.newInstanceFromXML(e);
在这种情况下,我认为它应该只调用一个空方法(即{})。 所有子类都将被强制实现静态方法,因此在调用静态方法时它们都会很好。 那么为什么这不可能呢?
编辑:我想我正在寻找比“因为这就是Java的方式”更深层次的答案。
是否有一个特殊的技术原因导致静态方法无法被覆盖? 也就是说,为什么Java的设计者决定使实例方法可覆盖但不是静态方法?
编辑:我的设计的问题是我正在尝试使用接口来强制执行编码约定。
也就是说,界面的目标是双重的:
我希望IXMLizable接口允许我将实现它的类转换为XML元素(使用多态,工作正常)。
如果有人想要创建一个实现IXMLizable接口的类的新实例,他们将始终知道将有一个newInstanceFromXML(Element e)静态构造函数。
除了在界面中添加评论之外,还有其他方法可以确保这一点吗?
编辑:从Java 8开始,接口中现在允许使用静态方法。
24个解决方案
461 votes
Java 8允许静态接口方法
使用Java 8,接口可以具有静态方法。 cozy们还可以拥有具体的实例方法,但不是实例领域。
这里有两个问题:
在过去的糟糕时期,为什么接口不能包含静态方法?为什么不能覆盖静态方法?
接口中的静态方法
没有强大的技术理由说明为什么接口在以前的版本中没有静态方法。 这可以通过重复问题的海报很好地总结出来。 静态接口方法最初被认为是一种小的语言变化,然后有一个官方提议将它们添加到Java 7中,但后来由于不可预见的复杂性而被删除。
最后,Java 8引入了静态接口方法,以及具有默认实现的覆盖实例方法。 但它们仍然不能有实例字段。 这些功能是lambda表达式支持的一部分,您可以在JSR 335的H部分中阅读更多相关内容。
覆盖静态方法
第二个问题的答案有点复杂。
静态方法在编译时可以解析。 动态分派对于实例方法是有意义的,其中编译器无法确定对象的具体类型,因此无法解析要调用的方法。 但是调用静态方法需要一个类,并且由于该类在编译时是静态已知的,因此动态调度是不必要的。
有关实例方法如何工作的一些背景知识是必要的,以了解这里发生了什么。 我确信实际的实现是完全不同的,但让我解释一下方法调度的概念,它可以准确地模拟观察到的行为。
假设每个类都有一个哈希表,它将方法签名(名称和参数类型)映射到实际的代码块以实现该方法。 当虚拟机尝试在实例上调用方法时,它会查询对象的类,并在类的表中查找请求的签名。 如果找到方法体,则调用它。 否则,获取该类的父类,并在那里重复查找。 这将继续,直到找到该方法,或者没有更多的父类 - 这导致Foo。