从List 扩展为Java中的List 类型的列表?

时间:2022-12-08 11:42:49

I think the title should explain it all but just in case...

我认为标题应该解释所有,但以防万一......

I want to know what risks and potential issues relating to casting can arise from the following snippet of Java code:

我想知道以下Java代码片段可能产生与转换相关的风险和潜在问题:

List<? extends MyObject> wildcardList = someAPI.getList();
List<MyObject> typedList = (List<MyObject>) wildcardList;

My thoughts are that all objects in the wildcardList should be an instance of MyObject (exact type or subclass) and so whenever objects are retrieved from typedList then there should never be a ClassCastException. Is this correct? If so why does the compiler generate a warning?

我的想法是wildcardList中的所有对象都应该是MyObject的实例(精确类型或子类),因此每当从typedList检索对象时,就不应该有ClassCastException。它是否正确?如果是这样,为什么编译器会生成警告?

5 个解决方案

#1


7  

There should be no problem as long as just you retrieve objects from the list. But it could result in runtime exception if you invoke some other methods on it like the following code demonstrate:

只要您从列表中检索对象就应该没有问题。但是,如果您在其上调用其他方法,则可能会导致运行时异常,如下面的代码所示:

    List<Integer> intList = new ArrayList<Integer>();
    intList.add(2);

    List<? extends Number> numList = intList;
    List<Number> strictNumList = (List<Number>) numList;
    strictNumList.add(3.5f);

    int num = intList.get(1); //java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer

#2


2  

You are correct about retrieving objects from typedList, this should work.

你是否正确从typedList检索对象,这应该工作。

The problem is when you later add more objects to typedList. If, for instance, MyObject has two subclasses A and B, and wildcardList was of type A, then you can't add a B to it. But since typedList is of the parent type MyObject, this error will only be caught at runtime.

问题是您稍后向typedList添加更多对象。例如,如果MyObject有两个子类A和B,而wildcardList的类型为A,那么就不能向它添加B。但由于typedList属于父类型MyObject,因此只会在运行时捕获此错误。

#3


1  

Consider you do something like:

考虑你做的事情如下:

List<ChildClassOne> childClassList = new ArrayList<ChildClassOne>();
childClassList.add(childClassOneInstanceOne);
childClassList.add(childClassOneInstanceTwo);

List<? extends MyObject> wildcardList = childClasslist; // works fine - imagine that you get this from a method that only returns List<ChildClassOne>
List<MyObject> typedList = (List<MyObject>) wildcardList; // warning

typedList.add(childClassTwoInstanceOne); // oops my childClassList now contains a childClassTwo instance
ChildClassOne a = childClassList.get(2); // ClassCastException - can't cast ChildClassTwo to ChildClassOne

This is the only major problem. But if you only read from your list it should be ok.

这是唯一的主要问题。但如果你只从列表中读取它应该没问题。

#4


0  

This is similar to

这类似于

List<Object> obj = (List<Object>) new ArrayList<String>();

I hope the problem is evident. List of subtypes can't be cast to Lists of supertypes.

我希望这个问题很明显。子类型列表不能转换为超类型列表。

#5


0  

In addition to the answers already posted, take a look at the following

除了已发布的答案,请查看以下内容

The compiler generates a warning incase an element from the type is accessed later in your code and that is not the generic type defined previously. Also the type information at runtime is not available.

编译器会生成警告,此类型中的元素将在稍后的代码中访问,而不是先前定义的泛型类型。此外,运行时的类型信息也不可用。

#1


7  

There should be no problem as long as just you retrieve objects from the list. But it could result in runtime exception if you invoke some other methods on it like the following code demonstrate:

只要您从列表中检索对象就应该没有问题。但是,如果您在其上调用其他方法,则可能会导致运行时异常,如下面的代码所示:

    List<Integer> intList = new ArrayList<Integer>();
    intList.add(2);

    List<? extends Number> numList = intList;
    List<Number> strictNumList = (List<Number>) numList;
    strictNumList.add(3.5f);

    int num = intList.get(1); //java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer

#2


2  

You are correct about retrieving objects from typedList, this should work.

你是否正确从typedList检索对象,这应该工作。

The problem is when you later add more objects to typedList. If, for instance, MyObject has two subclasses A and B, and wildcardList was of type A, then you can't add a B to it. But since typedList is of the parent type MyObject, this error will only be caught at runtime.

问题是您稍后向typedList添加更多对象。例如,如果MyObject有两个子类A和B,而wildcardList的类型为A,那么就不能向它添加B。但由于typedList属于父类型MyObject,因此只会在运行时捕获此错误。

#3


1  

Consider you do something like:

考虑你做的事情如下:

List<ChildClassOne> childClassList = new ArrayList<ChildClassOne>();
childClassList.add(childClassOneInstanceOne);
childClassList.add(childClassOneInstanceTwo);

List<? extends MyObject> wildcardList = childClasslist; // works fine - imagine that you get this from a method that only returns List<ChildClassOne>
List<MyObject> typedList = (List<MyObject>) wildcardList; // warning

typedList.add(childClassTwoInstanceOne); // oops my childClassList now contains a childClassTwo instance
ChildClassOne a = childClassList.get(2); // ClassCastException - can't cast ChildClassTwo to ChildClassOne

This is the only major problem. But if you only read from your list it should be ok.

这是唯一的主要问题。但如果你只从列表中读取它应该没问题。

#4


0  

This is similar to

这类似于

List<Object> obj = (List<Object>) new ArrayList<String>();

I hope the problem is evident. List of subtypes can't be cast to Lists of supertypes.

我希望这个问题很明显。子类型列表不能转换为超类型列表。

#5


0  

In addition to the answers already posted, take a look at the following

除了已发布的答案,请查看以下内容

The compiler generates a warning incase an element from the type is accessed later in your code and that is not the generic type defined previously. Also the type information at runtime is not available.

编译器会生成警告,此类型中的元素将在稍后的代码中访问,而不是先前定义的泛型类型。此外,运行时的类型信息也不可用。