2010-03-11 84 views
1

我正在推崇一個本土的DAO容器,希望能夠讓這個類變得通用。它在內部使用ArrayList來存儲檢索到的對象。將泛型列表轉換爲非泛型列表有什麼含義?

該類的一個用法是將容器的列表放入請求範圍,並且由於Websphere的限制,我無法將通用List<Foo>傳遞到請求範圍(Websphere無法處理超出範圍的泛型-box)

如果我和我的重構先走,我將需要轉換/施放List<Foo>到非通用List對象..

// Boils down to this... 
List<Foo> listFoo = new FooListing().findAllFoo(); 
List listThings = listFoo; 
request.setAttribute("listThings", listThings); 

什麼是扭轉這樣的generification的影響?我應該避免做這種操作嗎?

編輯:的代碼片斷是詳細明確地證明什麼,我描述..

+0

您不需要將中間任務分配給listThings;您可以直接將listFoo設置爲請求。 – 2010-03-11 06:44:45

回答

3

如果列表中的組件類型不匹配預期的類型,是沒有問題的。

Java中的泛型只用於編譯器的類型檢查,它們在運行時不起作用。如果您使用的是不支持泛型的較舊的庫,則別無選擇,只能忽略泛型。 事情應該繼續工作,因爲這個系統的設計考慮了向後兼容性。因此,所有你正在失去的是編譯時類型檢查(它會讓你回到Java處於1.4的地方,這意味着如果類型匹配,一切都會工作,否則,你將得到ClassCastExceptions或其他運行時不需要的行爲)。

不過,我覺得你可以只寫

request.setAttribute("listThings", listFoo); 

此方法需要任何類型的對象。即使它想要一個List,你仍然可以通過一個List<Foo>(這仍然是一個List)。

+0

很酷,只是想明確說明我在代碼示例中描述的是什麼 – brasskazoo 2010-03-11 06:21:55

+0

您可以將您的'List '傳遞給每個需要非通用列表的方法。 WebSphere不能干預這一點。這就是向後兼容性的工作原理。 – Thilo 2010-03-11 06:25:37

0

首先,你不能將泛型轉換爲非泛型列表,所以你必須轉換它。

其次,通用列表的兩個主要優點是1)它確保所有對象都是指定的類型; 2)它允許您直接訪問對象集合的方法而不需要重新對其進行重新設置。這使您可以編寫更清晰的代碼,並節省一些處理週期,從而不必回頭和後退。

然而,這些優點都不是最迫切的需求。如果你不能使用它們,你不會注意到性能的差異。儘管如此,你的代碼可能看起來有點混亂。

+1

您絕對可以將泛型轉換爲非泛型列表。你可能不得不壓制警告,但你絕對可以做到。這是有道理的,因爲它們在擦除後是完全相同的類型。 – polygenelubricants 2010-03-11 06:22:14

+0

「你不能將泛型轉換爲非泛型列表」。你可以寫'List x =(List)listFoo'。 – Thilo 2010-03-11 06:23:11

+0

啊我的不好。我一定會一直在想「你不能把一個通用列表放到另一個通用列表中」,並把它混淆在我的腦海中。 – 2010-03-11 06:26:08

2

Java使用「類型擦除」爲仿製藥 - 本質上意味着編譯器檢查的仿製藥,但運行時忘記所有關於它,只是把它當作對象的列表*

每當你治療List<Foo>只是一個List,你不會得到編譯器檢查,以確保你不會把Bla放到你的列表中。所以如果你打電話給List<Foo>.get(),你會得到一個ClassCastException,並且它變成了一個Bla隱藏在列表中。但是隻有當你的代碼在你的列表中放入一個Bla時纔會發生這種情況。

如果你wan't謹慎,那麼如果你通過List<Foo>作爲一個列表來任何可能添加非富到列表中,不要把它當作一個List<Foo>每當你訪問它,但治療它作爲Objects的列表並添加instanceof檢查。

*部分信息可在運行時訪問,但不要讓事情複雜化。

+0

幸運的是,在這種情況下使用列表僅用於顯示目的,所以沒有爆炸的風險在我們的臉上 – brasskazoo 2010-03-11 06:31:59

0

我對Weblogic Portal有類似的問題。在這種情況下只需使用非泛型類型。

1

泛型類型的「非泛型」版本稱爲「原始類型」。

在請求原始等價物時傳遞一般類型通常是可以的。這實際上是Java中泛型工作的主要原因(使用擦除):實現「基因化」代碼和泛型前代碼之間的互操作性。

你需要小心的是,如果你傳遞一個List<Foo>的東西,askes的List,他們可能把非Foo物體插入List最主要的。你不會得到任何編譯時間檢查來幫助你。您得到一些運行時檢查:當您使用一種方法返回上的Foo並且必須返回非Foo時,將會拋出ClassCastException

如果你想要更快的失效行爲,你可以用包裝Collections.checkedList()來獲得一個List來檢查插入時元素的類型。

如果Foo本身是一個通用類型,情況會變得更加複雜。運行時檢查僅在具體化類型上完成(即:刪除了泛型類型參數的類型),所以如果您給它們一個List<Set<Bar>>並且它們插入Set<Baz>Set,那麼您將不會知道,因爲元素的運行時/具體化類型無論哪種方式都是Set