爲何不能在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, " , ")));
    }
}
相關文章
相關標籤/搜索