6

这件事把我难住了。我有一堂课如下:

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>? 这对我来说没有任何意义。

我搞不清楚了。我该怎么做才能完成这项工作?我想这与泛型协方差有关,但此时我不知道这里出了什么问题。有人可以指出正确的方向吗?谢谢。

4

7 回答 7

3

不是每个List<MyType>(动物)都是MyList(牛)

您正在将动物添加到奶牛列表中

于 2013-05-27T06:44:49.143 回答
2

我会建议一些参数:

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");
    }
}
于 2013-05-27T07:09:33.873 回答
1

据我回忆,类型转换列表的正确方法是使用泛型。就像是:

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

但是我不确定这段代码背后的理论。

于 2013-05-27T06:48:06.067 回答
1

您已定义List<MyList>(即 列表MyList)。这意味着您只能在其中添加实例MyList。如果您正在使用addAll(),您可以添加MyList. 但是您正在尝试添加List<MyType>. MyType绝对不是MyList

而且您显然不能List转换为MyList.

于 2013-05-27T06:42:23.550 回答
1

为什么会出现这个错误

代码形式上是正确的。您几乎可以将任何对象转换为任何其他对象,并且代码将编译。如果强制转换无效,则会ClassCastException抛出运行时。

您的 IDE 可以在编译期间检测到不确定的强制转换并抱怨它们。作为警告或错误。这是配置问题。显然 OPs IDE 被配置为使这样的代码闻起来是编译错误

为什么这个演员表不安全

您可以通过以下方式回答您的问题:

你能创建一个List<MyType>不是 a 的SpecialList吗?

你不能投一个List<MyType>toSpecialList因为可能有一些对象将会是List<MyType>并且实际上不会是SpecialList

解决方案

更改您的应用架构

你可以做两件事——要么SpecialList在你的代码中使用类,要么使用通用的List<MyType>.

换句话说,要么改变:

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

或更改

private List<SpecialList> bigListprivate 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);
    }
}
于 2013-05-27T06:55:44.923 回答
0

这在我的 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
    }

这是我的班级

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);
    }
}

没有编译时错误或运行时异常

于 2013-05-27T07:08:52.767 回答
0
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>其中,则会出现错误。

为什么 :

  • 泛型意味着参数化类型。
  • Generic 添加了 TYPE SAFETY。
  • 这意味着,使用泛型,所有转换都是自动和隐式的,
    它们在显式添加和检索列表中的对象时不需要类型转换

实时场景:

如果机动车部门提供司机名单。我们认为 aList<Driver>是 a List<Person>,假设 Driver 是 Person 的子类型。

如果是这种情况,我们可以将不是司机的新人添加到列表中。

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

解决上述问题:

您可以将通配符与泛型一起使用。从文档http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html检查此链接

于 2013-05-27T07:40:49.193 回答