为何不能在Java接口中定义静态方法?

编辑: 从Java 8开始,接口中如今容许使用静态方法。 java

例子以下: 设计模式

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

固然这行不通。 可是为何不呢? oracle

可能的问题之一是,当您致电时会发生什么: ide

IXMLizable.newInstanceFromXML(e);

在这种状况下,我认为它应该只调用一个空方法(即{})。 全部子类都将被强制实现static方法,所以在调用static方法时它们都很好。 那为何不可能呢? 函数

编辑:我想我正在寻找比“由于这就是Java的方式”更深的答案。 this

有某种特殊的技术缘由为何不能覆盖静态方法? 也就是说,为何Java的设计者决定使实例方法可重写而不是静态方法? 编码

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

也就是说,该接口的目标是双重的: 设计

  1. 我但愿IXMLizable接口容许我将实现它的类转换为XML元素(使用多态性,效果很好)。 code

  2. 若是有人想建立一个实现IXMLizable接口的类的新实例,他们将始终知道将有一个newInstanceFromXML(Element e)静态构造函数。

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


#1楼

接口中须要静态方法是什么,当您没必要建立对象实例时,基本上使用静态方法。整个接口的思想是引入OOP概念,并引入您从概念中转移出来的静态方法。


#2楼

Why can't I define a static method in a Java interface?

接口中的全部方法都是显式抽象的,所以您不能将它们定义为静态的,由于静态方法不能是抽象的。


#3楼

能够实现的是静态接口(而不是接口中的静态方法)。 全部实现给定静态接口的类都应实现相应的静态方法。 您可使用如下方法从任何Class clazz获取静态接口SI

SI si = clazz.getStatic(SI.class); // null if clazz doesn't implement SI
// alternatively if the class is known at compile time
SI si = Someclass.static.SI; // either compiler errror or not null

而后能够调用si.method(params) 。 这将颇有用(例如,对于工厂设计模式),由于您能够从编译时未知类中获取(或检查其实现)SI静态方法实现! 动态分派是必需的,您能够经过扩展类(经过静态接口调用时)来覆盖类的静态方法(若是不是最终方法)。 显然,这些方法只能访问其类的静态变量。


#4楼

随着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

提示:调用静态接口方法不须要任何类实现。 确实发生这种状况是由于超类中静态方法的相同规则适用于接口上的静态方法。


#5楼

当我意识到Java 8解决了这个问题时,我认为我但愿解决当前正在研究的场景(使用Java 7锁定),在该场景中能够在接口中指定静态方法会有所帮助。

我有几个枚举定义,其中我已定义了“ id”和“ displayName”字段以及因为各类缘由而评估值的辅助方法。 实现接口使我能够确保使用getter方法,但不能使用静态辅助方法。 做为一个枚举,确实没有一种干净的方法能够将帮助程序方法卸载到继承的抽象类等中,所以必须在枚举自己中定义这些方法。 另外,由于它是一个枚举,因此您永远没法将其做为实例对象实际传递并将其视为接口类型,可是我但愿可以经过接口要求存在静态助手方法,这是我想要的Java 8支持它。

这是说明我观点的代码。

接口定义:

public interface IGenericEnum <T extends Enum<T>> {
    String getId();
    String getDisplayName();
    //If I was using Java 8 static helper methods would go here
}

一个枚举定义的示例:

public enum ExecutionModeType implements IGenericEnum<ExecutionModeType> {
    STANDARD ("Standard", "Standard Mode"),
    DEBUG ("Debug", "Debug Mode");

    String id;
    String displayName;

    //Getter methods
    public String getId() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    //Constructor
    private ExecutionModeType(String id, String displayName) {
        this.id = id;
        this.displayName = displayName;
    }

    //Helper methods - not enforced by Interface
    public static boolean isValidId(String id) {
        return GenericEnumUtility.isValidId(ExecutionModeType.class, id);
    }

    public static String printIdOptions(String delimiter){
        return GenericEnumUtility.printIdOptions(ExecutionModeType.class, delimiter);
    }

    public static String[] getIdArray(){
        return GenericEnumUtility.getIdArray(ExecutionModeType.class);
    }

    public static ExecutionModeType getById(String id) throws NoSuchObjectException {
        return GenericEnumUtility.getById(ExecutionModeType.class, id);
    }
}

通用枚举实用程序定义:

public class GenericEnumUtility {
    public static <T extends Enum<T> & IGenericEnum<T>> boolean isValidId(Class<T> enumType, String id) {       
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(enumOption.getId().equals(id)) {
                return true;
            }
        }

        return false;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String printIdOptions(Class<T> enumType, String delimiter){
        String ret = "";
        delimiter = delimiter == null ? " " : delimiter;

        int i = 0;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(i == 0) {
                ret = enumOption.getId();
            } else {
                ret += delimiter + enumOption.getId();
            }           
            i++;
        }

        return ret;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String[] getIdArray(Class<T> enumType){
        List<String> idValues = new ArrayList<String>();

        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            idValues.add(enumOption.getId());
        }

        return idValues.toArray(new String[idValues.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Enum<T> & IGenericEnum<T>> T getById(Class<T> enumType, String id) throws NoSuchObjectException {
        id = id == null ? "" : id;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(id.equals(enumOption.getId())) {
                return (T)enumOption;
            }
        }

        throw new NoSuchObjectException(String.format("ERROR: \"%s\" is not a valid ID. Valid IDs are: %s.", id, printIdOptions(enumType, " , ")));
    }
}
相关文章
相关标签/搜索