2008-11-24 77 views
9

我該如何使這個Java通用轉換?我該如何使這個Java通用轉換?

public interface IField { 

} 


class Field implements IField { // package private class 

} 

public class Form { 
    private List<Field> fields; 


    public List<IField> getFields() { 
    return this.fields; 

    } 

} 

return語句拋出一個編譯器錯誤(我知道原因 - 我讀了泛型教程),但它是非常方便的寫這樣的代碼。

如果我將「fields」聲明爲List,那麼我需要在Form類的其他方法中使用大量強制類型轉換爲Field。

我可以強迫那該死的編譯器彎曲它的規則並編譯該返回語句嗎?

在此先感謝。

+0

作爲一個側面說明,this.fields被typoed爲this.fiedls和我沒有足夠高的聲望編輯其他人的帖子。 – Powerlord 2008-11-24 13:36:23

+0

@R Bemrose - 修好了,謝謝。 – 2008-11-24 13:46:53

回答

17

更好的解決方案,國際海事組織,是改變你的方法的簽名使用綁定的通配符:

public List<? extends IField> getFields() 

這將讓來電者對待任何事情來了「走出去」的列表作爲IField的,但它不會讓調用者將任何東西添加到列表中(沒有投射或警告),因爲他們不知道列表的「真實」類型是什麼。

12

碰巧你可以這樣做,因爲Java泛型只是嫁接而不是類型系統的一部分。

你可以做

return (List<IField>)(Object)this.fields; 

,因爲所有List<T>對象相同的基本類型。

請記住,這允許任何人在您的列表中放置任何類型的實施IField,因此如果您的收藏夾不是隻讀的,則可能會遇到困難。

+0

當然,我會讓它只讀 - 謝謝美國 – 2008-11-24 13:26:06

0

陽光是正確的,你可以投它。

另一個解決方法是仔細檢查確實需要List<Field>,或者是否可以將內部變量fields更改爲List<IField>

只要您只使用IField接口上的列表內容中的方法,您就應該能夠進行簡單的交換。

5

不要這樣做。

A List<Field>不是List<IField>。你可以試着強制編譯器接受(我認爲這是不可能的,我希望這是不可能的),但這會讓你陷入困境。編譯器將允許用戶將從IField派生的AnotherField引入給定的List中,以打破不變式,並打破泛型提供的類型安全性。之後使用List<Field>將會中斷,因爲提取奇怪的元素將會使隱式投射失敗,您不會期望它發生。

如果您確實需要返回List<IField>而不是List<Field>,那麼我會建議您生成一個填充了相同元素的新列表。如果您可以修改您的界面,請轉至Jon Skeets解決方案。

2

如果來電者不需要能夠修改列表:

return Collections.<IField>unmodifiableList(this.fields);