编辑:从Java 8开始,静态方法现在被允许出现在接口中。
下面是例子:
public interface IXMLizable<T>
{
static T newInstanceFromXML(Element e);
Element toXMLElement();
}
当然这行不通。但为什么不呢?
其中一个可能的问题是,当你调用:
IXMLizable.newInstanceFromXML(e);
在这种情况下,我认为它应该只调用一个空方法(即{})。所有子类都必须实现静态方法,所以在调用静态方法时它们都没问题。那为什么不可能呢?
编辑:我想我正在寻找比“因为这就是Java”更深刻的答案。
静态方法不能被覆盖是否有特殊的技术原因?也就是说,为什么Java的设计者决定让实例方法可重写,而不是静态方法?
编辑:我的设计的问题是我试图使用接口来执行编码约定。
也就是说,接口的目标有两个:
我希望IXMLizable接口允许我将实现它的类转换为XML元素(使用多态性,工作正常)。
如果有人想创建实现IXMLizable接口的类的新实例,他们总是知道会有一个newInstanceFromXML(Element e)静态构造函数。
除了在界面中添加注释之外,还有其他方法可以确保这一点吗?
一个接口永远不能被静态地解引用,例如issomething .member。接口总是通过引用该接口子类实例的变量来解除引用。因此,如果没有其子类的实例,接口引用永远不可能知道它引用的是哪个子类。
Thus the closest approximation to a static method in an interface would be a non-static method that ignores "this", i.e. does not access any non-static members of the instance. At the low-level abstraction, every non-static method (after lookup in any vtable) is really just a function with class scope that takes "this" as an implicit formal parameter. See Scala's singleton object and interoperability with Java as evidence of that concept.
And thus every static method is a function with class scope that does not take a "this" parameter. Thus normally a static method can be called statically, but as previously stated, an interface has no implementation (is abstract).
Thus to get closest approximation to a static method in an interface, is to use a non-static method, then don't access any of the non-static instance members. There would be no possible performance benefit any other way, because there is no way to statically link (at compile-time) a ISomething.member(). The only benefit I see of a static method in an interface is that it would not input (i.e. ignore) an implicit "this" and thus disallow access to any of the non-static instance members. This would declare implicitly that the function that doesn't access "this", is immutate and not even readonly with respect to its containing class. But a declaration of "static" in an interface ISomething would also confuse people who tried to access it with ISomething.member() which would cause a compiler error. I suppose if the compiler error was sufficiently explanatory, it would be better than trying to educate people about using a non-static method to accomplish what they want (apparently mostly factory methods), as we are doing here (and has been repeated for 3 Q&A times on this site), so it is obviously an issue that is not intuitive for many people. I had to think about it for a while to get the correct understanding.
在接口中获取可变静态字段的方法是在接口中使用非静态getter和setter方法,来访问子类中的静态字段。旁注,显然不可变静态可以在带有静态final的Java接口中声明。
有几个答案讨论了可覆盖静态方法概念的问题。然而,有时你会遇到一种模式,它似乎正是你想要使用的。
例如,我使用对象关系层,该层有值对象,但也有用于操作值对象的命令。由于各种原因,每个值对象类都必须定义一些静态方法,以便框架找到命令实例。例如,要创建一个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.
随着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
提示:调用静态接口方法不需要由任何类实现。当然,这是因为适用于超类中的静态方法的规则同样适用于接口上的静态方法。