我有一個enum
存儲爲一個數據庫表中的一些元數據:Java:如何實現<??擴展...>至<E>
static enum DataTable implements TableMetaData {
HISTORIES ("h", Hx.class, HxColumn.HPI_ID),
:
:
private final String e_alias;
private final Class<? extends Row> e_tbl;
private final ColumnMetaData e_idCol;
DataTable(String al,
Class <? extends Row> c1,
ColumnMetaData id)
{...}
@Override public Class<? extends Row> modelClass() { return this.e_tbl; }
:
:
}
感興趣的領域是e_tbl
存儲對應於數據庫表中的模型對象類。該項目中的所有模型對象類都實現了一個接口。我希望能夠訪問此字段以生成此類的實例。
我的問題是,我使用了一個未檢查的轉換,我不知道是否安全,我還沒有弄清楚如何執行運行時檢查以確保模型對象匹配。這裏是演員陣容的代碼:
static final <E extends Row> List<E> doQuery (
final List<JdbcValue> pars,
final String sql,
final TableMetaData dm
)
{
List<E> result = new ArrayList<E>();
@SuppressWarnings("unchecked")
Class<E> cls = (Class<E>) dm.modelClass();
:
:
}
我相信這是一個危險演員。該查詢旨在生成E
實例,並且將使用所提供的枚舉常量中包含的模型類來創建這些實例。問題是我不知道E
與枚舉中存儲的類標記相匹配。這是Class.asSubclass()
似乎無法幫助我的情況。
問題是我有一個字段是<? extends Row>
,我需要使它與<E extends Row>
兼容。
一個解決方案是重構該方法,它需要參數Class<E> cls
而不是枚舉。這將提供至少一些編譯時保證,類標記適用於正在生成的結果列表的類型。但是,這仍然不能讓我使用枚舉中的數據;在方法調用之前,我仍然必須將其投射出去。
有沒有可以使用的支票?
============================================== ====
修訂14年12月6日
在我看來,這是一個問題,如果沒有良好的,乾淨的解決方案。
枚舉不支持泛型類型參數(它們不能)。
每次嘗試將參數化類型存儲在枚舉常量中時,編譯時都會出現不兼容的類型信息。
建議使用參數化的類型安全單例模式,使編譯器能夠檢查類型安全性,但是我擁有的API被這些枚舉類所滲透,我不覺得我可以將它們重構爲常規類。
爲了限制損壞,不知下面的推理是正確的:
與枚舉常數相關聯的數據是靜態的和最終;在這裏它也是一成不變的。
我完全控制該進入枚舉常量的數據,所以我知道在運行時,該
e_tbl
場總是會有些類型的擴展的Class
對象。
這些假設承認兩種方法,我認爲它們有相同的缺陷。在枚舉類,存取方法被改寫爲:
@Override public <E extends Row> Class<E> modelclass() {
@SuppressWarning("unchecked")
Class<E> cls = (Class<E>) this.e_tbl;
return this.e_tbl; }
我可以將數據存儲到枚舉到使用原始類型的字段。原始類型與通用訪問器方法互操作,因此它會編譯但會生成警告。
我可以將數據存儲到枚舉到使用
<? extends Row>
通配符類型的字段。這不會使用通用訪問器方法(<E> extends Row>
)進行編譯,因此我必須使用未經檢查的強制轉換。警告仍然生成。
因爲我知道枚舉數據總是延伸,我認爲這可能是好的。我不能做的是保證正在檢索的枚舉數據適合生成的List
類型。但我不認爲除了記錄API用戶必須爲正在返回的查詢發送正確的TableMetaData常量或結果將是「未定義」之外,沒有其他方法可以控制這一點。
由於枚舉不適用於泛型類型,我不認爲有更好的解決方案。
很對。不過,enum中的數據(它被指定爲提供模型對象類類型標記)應該可以以這種方式使用,這似乎也是「正確的」。如果我爲參數手動輸入'Hx.class',而不是使用'dm.modelClass()',即使它們是相同的,我也可以讓所有的東西都可以工作。 – scottb 2014-12-02 18:48:51
所有這些通用類型在運行時不存在。所以在這一點上什麼都不應該發生,甚至可能不會晚。 (轉換成功後,請參閱http://ideone.com/B3nTcy崩潰)。你需要一個具體的東西來與運行時進行比較,那些'E'不再存在了。 – zapl 2014-12-02 19:17:32