繁体   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