为什么我不能在Java界面中定义静态方法?

问题:

这是一个例子:

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

当然这不行。但为什么不呢
其中一个可能的问题是,当您打电话时会发生什么:

IXMLizable.newInstanceFromXML(e);

在这种情况下,我认为它应该只是调用一个空的方法(即{})。所有的子类都将被强制实现静态方法,所以调用静态方法时都会很好。那么为什么这不可能呢?
 编辑:我想我正在寻找比“因为Java的方式”更深入的答案。
静态方法不能被覆盖有什么特殊的技术原因吗?也就是说,为什么Java的设计者决定使实例方法可以重写而不是静态方法?
 编辑:我的设计的问题是我正在尝试使用接口来执行编码约定。
也就是说,接口的目标是双重的:

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

有没有其他方法来确保这个,除了只是在界面中发表评论?
 编辑: As of Java 8, static methods are now allowed in interfaces.

回答:

Java 8允许静态接口方法

使用Java 8,接口can具有静态方法。他们也可以有具体的实例方法,而不是实例字段。
这里真的有两个问题:

  1. 为什么在不好的旧时代,界面不能包含静态方法?
  2. 为什么静态方法不能被覆盖?

接口中的静态方法

没有强大的技术原因,为什么接口在以前的版本中不能有静态方法。这是重复问题的summed up nicely by the poster。静态接口方法最初被认为是a small language change,,然后有an official proposal将它们添加到Java 7中,但后来dropped due to unforeseen complications.
最后,Java 8引入了静态接口方法,以及具有默认实现的可重用实例方法。他们仍然不能有实例字段。这些功能是lambda表达式支持的一部分,您可以在Part H of JSR 335.中阅读更多关于它们的内容

覆盖静态方法

第二个问题的答案有点复杂。
静态方法在编译时可解析。动态调度对于实例方法是有意义的,编译器无法确定对象的具体类型,因此无法解析要调用的方法。但是调用静态方法需要一个类,并且由于该类是已知的statically – 在编译时 – 动态调度是不必要的。
了解实例方法如何工作的一点背景是必要的,以了解这里发生了什么。我确定实际的实现是完全不同的,但是让我解释一下我的方法调度的概念,它准确地模拟了观察行为。
假设每个类都有一个将方法签名(名称和参数类型)映射到实际的代码块的哈希表,以实现该方法。当虚拟机尝试调用实例上的方法时,它会查询对象的类,并在类的表中查找请求的签名。如果找到方法体,则调用它。否则,获取该类的父类,并在那里重复查找。直到发现方法,或者没有更多的父类,这会导致NoSuchMethodError
如果一个超级类和一个子类在它们的表中都有相同方法签名的条目,则首先遇到子类的版本,并且超级类的版本永远不会被使用 – 这是一个“覆盖”。
现在,假设我们跳过对象实例,然后从一个子类开始。该决议可以如上所述,给你一种“可以覆盖”的静态方法。解决方案都可以在编译时进行,因为编译器是从一个已知的类开始的,而不是等到运行时为其类查询未指定类型的对象。在“覆盖”静态方法中没有意义,因为可以总是指定包含所需版本的类。

构造函数“接口”

这里有一些更多的材料来解决最近编辑的问题。
这听起来像你想要为IXMLizable的每个实现有效地要求一个类构造函数。忘记使用界面强制执行一分钟,并假装你有一些符合这个要求的类。你会如何使用它?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

由于您必须在构建新对象时明确指定具体的类型Foo,所以编译器可以确认它确实具有必要的工厂方法。如果没有,那么什么?如果我可以实现一个缺少“构造函数”的IXMLizable,并且我创建一个实例并将其传递给你的代码,那么is一个IXMLizable具有所有必要的接口。
 Construction is part of the implementation,不是界面。任何与界面成功工作的代码都不关心构造函数。任何关心构造函数的代码都需要知道具体的类型,并且可以忽略该接口。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Why can’t I define a static method in a Java interface?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

70 + = 79