簡體   English   中英

與通用簽名接口的靜態方法

[英]Static Method in Interface with Generic signature

從Java 8開始,您可以在Interfaces中實現默認或靜態方法,如下所示

public interface DbValuesEnumIface<ID, T extends Enum<T>> {
   T fromId(ID id);

   ID getId();
   static String getDescriptionKey(){
      return "this is a test";
   }
}

我想聲明上面的靜態方法,其簽名使用實現類定義的邊界,因為方法的實現應該對所有人都相同,唯一不同的應該是聲明的泛型,如下:

public interface DbValuesEnumIface<ID, T extends Enum<T>> {

   public static T fromId(ID id) {
        if (id == null) {
            return null;
        }
        for (T en : T.values()) {
            if (en.getId().equals(id)) {
                return en;
            }
        }
    }

    ID getId();

    String getDescriptionKey();
}
...
public enum Statuses implements DbValuesEnumIface<Integer,Statuses>

因為T和ID不是靜態的而且不能從靜態上下文引用而中斷。

那么,如何修改上述內容以便成功編譯,如果不可能,那么應該如何實現上述目標以實現預期目的,同時避免實現類中的代碼重復。

由於static方法和類的類型參數(描述實例的參數化方式)之間沒有關系,因此必須使static方法本身具有通用性。 棘手的部分是使聲明正確描述所有需要的約束。 正如這個答案已經解釋過的那樣,你需要一個Class參數,否則,實現沒有機會獲得實際的類型參數:

public interface DbValuesEnumIface<ID, T extends Enum<T>> {

   public static
   <ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> T fromId(ID id, Class<T> type) {
        if (id == null) {
            return null;
        }
        for (T en : type.getEnumConstants()) {
            if (en.getId().equals(id)) {
                return en;
            }
        }
        throw new NoSuchElementException();
    }

    ID getId();

    String getDescriptionKey();
}

請注意, static方法的類型參數獨立於類的類型參數。 為清楚起見,您可以考慮給它們不同的名稱。

所以現在,給定enum Statuses implements DbValuesEnumIface<Integer,Statuses>示例,您可以使用Statuses status = DbValuesEnumIface.fromId(42, Statuses.class);


請注意,對於default方法,可以訪問實際類型,因為實現將提供提供enum類型方法 您只需要在interface聲明方法的存在:

public interface DbValuesEnumIface<ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> {

    public default T fromId(ID id) {
        if (id == null) {
            return null;
        }
        for (T en : getDeclaringClass().getEnumConstants()) {
            if (en.getId().equals(id)) {
                return en;
            }
        }
        throw new NoSuchElementException();
    }
    Class<T> getDeclaringClass();//no needed to implement it, inherited by java.lang.Enum
    ID getId();
    String getDescriptionKey();
}

但是,明顯的缺點是你需要一個目標實例來調用該方法,即Statuses status = Statuses.SOME_CONSTANT.fromId(42);

據我所知,沒有簡單的方法,首先你需要將你的方法改為default ,你可以在這里閱讀更多關於為何不能在靜態上下文中使用泛型的原因。

但即使你把它改成default東西仍然無法工作,因為你需要將枚舉的實例或類類型傳遞給該方法,如下所示:

public default T fromId(ID id, Class<T> t) {
        if (id == null) {
            return null;
        }
        for (T en : t.getEnumConstants()) {
            // dome something
        }
        return null;
}

現在你遇到了另一個問題,在fromId - 你知道的唯一一件事就是T擴展了一個enum - 而不是你的枚舉可能,因此getId (看起來你的枚舉似乎)根本就不為編譯器所知。

除了聲明一個界面之外,我不知道一個簡單的方法來完成這項工作,例如:

interface IID {
    public int getId();
} 

讓你的enum實現它:

static enum My implements IID {
    A {

        @Override
        public int getId() {
            // TODO Auto-generated method stub
            return 0;
        }

    };
}

並將聲明更改為:

public interface DbValuesEnumIface<ID, T extends Enum<My> & IID>

您可以從static更改為default ,它將成功編譯。

default EvaluationStatuses fromId(Integer id)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM