2017-05-23 31 views
1

推斷T的方法我有一個枚舉實現了一個接口。枚舉:如何從類<T>

enum MyEnum implements MyInterface { 
    ONE, TWO, THREE; 

    @Override 
    public MyEnum getFirst() { 
     return ONE; 
    } 
} 

接口:

interface MyInterface<T extends Enum<T>> { 
    T getFirst(); 
} 

我也有界限泛型類:

class MyClass <T extends Enum<T> & MyInterface> { 
    private T firstElement; 
    private Class<T> enumType; 

    MyClass (Class<T> enumType) { 
     this.enumType = enumType; 
    } 
} 

所以其主要思想是通過任何enum(這是農具MyIterface)成構造函數,然後使用它的常量。這對我有用。但我也想將這第一個元素存儲到firstElement私有字段中。我試過這樣的:

firstElement = ((MyInterface)enumType).getFirst(); 

但仍然沒有成功。我不能投java.lang.Class<T>MyInterface。任何想法如何實現這一目標?提前致謝!

更新:我的問題不是關於如何採取第一個枚舉常量。我知道.ordinal().values()[0];。我想創建可重用的泛型類,並將其與任何枚舉一起使用,並由一些接口標記。 好吧,讓它不是getFirst()方法。讓它成爲getDefault()

+2

@ΦXocę웃Пepeúpaツ所有枚舉繼承了該類,它有一定道理:) – niceman

+0

的可能的複製[當給方法名稱作爲字符串時,如何調用Java方法?](https://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the- method-name-as-a-string) – niceman

+1

enumType是Class類型的,它不會有你的枚舉方法。只有MyEnum.ONE,MyEnum.TWO等可用該方法。 – Sikorski

回答

1

我想你可以使用Supplier<T>作爲參數的構造函數,而不是Class<T>

class MyClass<T extends Enum<T> & MyInterface<T>> { 
    private T firstElement; 
    private Class<T> enumType; 

    @SuppressWarnings("unchecked") 
    MyClass (Supplier<T> enumSupplier) { 
     T actualEnum = enumSupplier.get(); 
     this.enumType = (Class<T>) actualEnum.getClass(); 
     this.firstElement = actualEnum.getFirst(); 
    } 
} 

那投拋出一個警告,但它可以安全地抑制,因爲Supplier<T>將返回T一個實例, T既是Enum<T>也是MyInterface<T>,所以actualEnum的等級將始終爲Class<T>

我想建議你一些更正:因爲MyInterface是通用的,你應該一直使用它與一般類型(這就是爲什麼我已經宣佈MyClassMyClass<T extends Enum<T> & MyInterface<T>>)。 MyEnum也是如此:它應該被定義爲MyEnum implements MyInterface<MyEnum>

有了上面的修改,您可以按如下現在創建的MyClass一個實例:

MyClass<MyEnum> myClass = new MyClass<>(() -> MyEnum.THREE); // Or ONE or TWO 

System.out.println(myClass.firstElement); // ONE 
1

從您的上下文我認爲你需要getFirst(),因爲你想獲得一個枚舉的第一個值。但是,根本不需要getFirst()。所有你需要的是這樣的:

class <T extends Enum<T> & MyInterface> MyClass { 
    private T firstElement; 
    private Class<T> enumType; 

    MyClass (Class<T> enumType) { 
     this.enumType = enumType; 
     firstElement = enumType.getEnumConstants()[0]; 
    } 
} 

您只需刪除所有這些getFirst()在所有類。

+1

不錯的建議,你忘了刪除'MyInterface' – niceman

+0

@niceman呃,恐怕OP可能會哭'MyInterface'是一個標記界面,不能刪除。例如[CopyOption](http://docs.oracle.com/javase/8/docs/api/java/nio/file/CopyOption.html)。 – glee8e

1

您只能在實現了MyInterface但不在其類上的枚舉對象上調用getFirst。你可以寫:

firstElement = enumType.getEnumConstants()[0].getFirst(); 
+1

但由於枚舉是有序的,我不明白爲什麼你想要'getFirst()'方法。 – wero

+0

謝謝,但我知道'.values()[0]','.ordinal()'和'.getEnumConstants()'。我的問題不在於如何獲得第一個枚舉常量。這是關於泛型。我會更新我的帖子。 –

+0

@YevhenDanchenko查看我的回答:'enumType.getEnumConstants()[0]'僅用於從類''獲取到'T'對象,然後調用'getFirst()'(或'getDefault()')這個對象。 – wero

0
interface MyInterface { 
    MyInterface getFirst(); 

    MyInterface[] getConstants(); 
} 

enum MyEnum implements MyInterface { 
    ONE, TWO, THREE; 

    @Override 
    public MyInterface getFirst() { 
     return ONE; 
    } 

    @Override 
    public MyInterface[] getConstants() { 
     return new MyInterface[] {ONE, TWO, THREE}; 
    } 
} 

class MyClass { 
    private MyInterface firstElement; 

    MyClass (MyInterface enumType) { 
     this.firstElement = enumType.getFirst(); 
    } 
} 

因此,使用上述的設計,我覺得你可以「通過任何枚舉(這是農具MyInterface的)到構造,然後用它的常數工作。」

+1

我的觀點是,當你使用像「enumType」這樣的屬性時,你沒有正確使用接口。因爲在某些時候,你必須寫一些類似「if(enumType == SomeType)」或if(enumType SomeType)的東西,而這些東西似乎不是一個好設計。接口主要用於取代這個'if else'邏輯(或開關)進行類型檢查。 – diogenesgg

+0

謝謝。這似乎是有道理的。也許我在架構方面有問題。 –