簡體   English   中英

Java泛型,列表列表

[英]Java generics, list of lists

這件事讓我難過。 我有一個課程如下:

public class SpecialList implements List<MyType> {
    // overriden methods
}

現在我有以下方法合同要尊重更高級別:

public class MyClass {
    private List<SpecialList> bigList = new ArrayList<SpecialList>();

    public void doStuff(List<MyType> list)
    {
        bigList.add((SpecialList)list); // does not compile - invalid cast
    }
}

我真的不確定我在這里做錯了什么。 我有一個實現List<MyType>接口的類,但是我不能將該類轉換為List<MyType> 這對我沒有任何意義。

我搞不清楚了。 我應該做些什么來完成這項工作? 我想這與泛型協方差有關,但此時我不知道這里有什么問題。 有人能指出正確的方向嗎? 謝謝。

不是每個List<MyType> (Animal)都是MyList (Cow)

你正在將動物添加到奶牛名單中

我會建議一些參數:

public class MyClass{
    private List<List<MyType>> bigList = new ArrayList<List<MyType>>();

    public <E extends List<MyType>> void doStuff(E list)
    {
        bigList.add(list);
    }
}

當您從bigList中檢索元素時,您無法專門化該元素,因為它來自通用列表。 如果你絕對需要施放它,也許你的類架構是不正確的。 或者你可以濫用這個:

public class MyClass{
    private List<List<MyType>> bigList = new ArrayList<List<MyType>>();

    public <E extends List<MyType>> void doStuff(E list)
    {
        bigList.add(list);
    }

    public <E extends List<MyType>> E getStuff(Class<E> myType,int i)
    {
        List<MyType> obj = bigList.get(i);
        if(myType.isInstance(obj)) return (E) obj;
        throw new SomeErrorHere("invalid type for index");
    }
}

您定義了List<MyList> (即MyList列表)。 這意味着您只能添加MyList實例。 如果你正在使用addAll()您可以添加的列表MyList 但是您正在嘗試添加List<MyType> MyType絕對不是MyList

你顯然無法將ListMyList

從我記得,使用泛型的類型列表的正確方法。 就像是:

bigList.add((List<MyList>)(List<?>)list);

但是我不確定這個代碼背后的理論。

為什么會發生此錯誤

代碼是正式的。 您可以將幾乎任何對象轉換為任何其他對象,代碼將被編譯。 如果強制轉換無效,則會拋出運行時ClassCastException

您的IDE可以檢測不確定的強制轉換並在編譯期間抱怨它們。 作為警告或錯誤。 這是一個配置問題。 顯然OPs IDE配置為使這樣的代碼聞起來編譯錯誤

為什么這個演員不安全

你可以回答這個問題來回答你的問題:

你能創建一個不是SpecialListList<MyType>嗎?

您不能將List<MyType> SpecialListSpecialList因為可能存在List<MyType>對象,並且實際上不是SpecialList

解決方案

更改您的應用架構

您可以執行兩項操作 - 使用您的代碼中的所有類SpecialList ,或使用通用List<MyType>

換句話說,要么改變:

doStuff(List<MyType> list)doStuff(SpecialList list)

或改變

private List<SpecialList> bigList to private List<List<MyType>> bigList

您必須決定是否需要通用接口列表或您自己的類在任何地方使用。 請記住,您可以將SpecialListList<MyType> ,因為所有SpecialList實例也是List<MyType>實例。 它反過來不起作用。

確保演員表始終有效

如果你絕對必須使這個設計工作,使用instanceof來檢查列表是否真的是一個SpecialList 像那樣:

public void doStuff(List<MyType> list)
{
    if (list instanceof SpecialList) {
        bigList.add((SpecialList)list);
    } else {
        SpecialList sl = new SpecialList(list); // I hope you have that constructor
        bigList.add(sl);
    }
}

這在我的Eclipse中工作,這是類SpecialList,Hello是MyType類的類

package a;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class SpecialList implements List<Hello> {

    //Overridden methods
    }

這個是Myclass

package a;

import java.util.ArrayList;
import java.util.List;

public class MyClass {
    private List<SpecialList> bigList = new ArrayList<SpecialList>();

    public void doStuff(List<Hello> list)
    {
        bigList.add((SpecialList)list);  //compiles good
    }
    public static void main(String[] args) {
        new MyClass().doStuff(null);
    }
}

沒有編譯時錯誤或運行時異常

List <MyList> is not same as List <MyType>.

讓我們簡單一點,看下幾行:

 *List<MyList> myList = new ArrayList<MyList>(); //1
  myList.add(new MyType);//2 ......Compile ERROR*

如果您嘗試將MyType實例添加到List<MyList> ,它將提供ERROR。

為什么:

  • 泛型是指參數化類型。
  • Generic添加了TYPE SAFETY。
  • 這意味着,通用所有演員都是自動和隱含的,
    在添加和恢復對象時,它們不需要進行類型轉換
    從列表中明確地說。

實時場景:

如果機動車部門提供司機名單。 我們認為List<Driver>List<Person> ,假設Driver是Person的子類型。

如果是這種情況,我們可以將不是司機的新人添加到列表中。

那就是所有人都不是司機。

解決上述問題:

您可以將Wildcards與泛型一起使用。 從文檔http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html查看此鏈接

暫無
暫無

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

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