例如,假设你有两个类:
public class TestA {}
public class TestB extends TestA{}
我有一个返回List<TestB>的方法,我想将该列表中的所有对象强制转换为TestB,以便最终得到List<TestB>。
例如,假设你有两个类:
public class TestA {}
public class TestB extends TestA{}
我有一个返回List<TestB>的方法,我想将该列表中的所有对象强制转换为TestB,以便最终得到List<TestB>。
当前回答
我知道的唯一方法就是复制:
List<TestB> list = new ArrayList<TestB> (
Arrays.asList (
testAList.toArray(new TestB[0])
)
);
其他回答
2022年回答
将一组超类型的List转换为一组子类型的List是没有意义的,任何人都不应该尝试或甚至考虑这样做。如果你认为你的代码需要这样做,你需要重写你的代码,使它不需要这样做。
对于这个问题,大多数访问者可能想要做相反的事情,这实际上是有道理的:
将子类型列表转换为超类型列表。
我发现的最好的方法是:
List<TestA> testAs = List.copyOf( testBs );
这样做有以下优点:
这是一个简洁的一行代码 它不会产生警告 如果你的列表是用list .of()创建的,它不会复制!! 最重要的是:它做了正确的事情。
为什么这是对的?
如果你看一下List.copyOf()的源代码,你会发现它的工作原理如下:
如果您的列表是用list .of()创建的,那么它将执行强制转换并返回它,而不复制它。 否则,(例如,如果你的列表是一个ArrayList(),)它将创建一个副本并返回它。
如果List<TestB>是一个<TestB>的数组列表,那么必须创建一个数组列表的副本。如果您将ArrayList<TestB>转换为List<TestA>,则可能会无意中将一个TestA添加到List<TestA>中,这将导致原始ArrayList<TestB>在TestB中包含一个TestA,这是内存破坏:试图迭代原始ArrayList<TestB>中的所有TestB将抛出ClassCastException。
另一方面,如果List<TestB>是使用List.of()创建的,那么它是不可更改的(*1),因此没有人会无意中向其添加一个TestA,因此可以将其强制转换为List<TestA>。
(*1) when these lists were first introduced they were called "immutable"; later they realized that it is wrong to call them immutable, because a collection cannot be immutable, since it cannot vouch for the immutability of the elements that it contains; so they changed the documentation to call them "unmodifiable" instead; however, "unmodifiable" already had a meaning before these lists were introduced, and it meant "an unmodifiable to you view of my list which I am still free to mutate as I please, and the mutations will be very visible to you". So, neither immutable or unmodifiable is correct. I like to call them "superficially immutable" in the sense that they are not deeply immutable, but that may ruffle some feathers, so I just called them "unchangeable" as a compromise.
简单地转换为List<TestB>就可以了;但它不起作用,因为您不能将一个参数的泛型类型强制转换为另一个参数。然而,你可以通过一个中间通配符类型进行强制转换,这是允许的(因为你可以强制转换到通配符类型,只是有一个未选中的警告):
List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;
我知道的唯一方法就是复制:
List<TestB> list = new ArrayList<TestB> (
Arrays.asList (
testAList.toArray(new TestB[0])
)
);
由于类型擦除,这是可能的。你会发现
List<TestA> x = new ArrayList<TestA>();
List<TestB> y = new ArrayList<TestB>();
x.getClass().equals(y.getClass()); // true
在内部,两个列表的类型都是List<Object>。出于这个原因,你不能将一个转换为另一个——没有什么可以转换的。
泛型的强制转换是不可能的,但是如果你以另一种方式定义列表,则可以将TestB存储在其中:
List<? extends TestA> myList = new ArrayList<TestA>();
在使用列表中的对象时,仍然需要进行类型检查。