例如,假设你有两个类:

public class TestA {}
public class TestB extends TestA{}

我有一个返回List<TestB>的方法,我想将该列表中的所有对象强制转换为TestB,以便最终得到List<TestB>。


当前回答

正如Steve Kuo提到的,您不能将List<TestB>转换为List<TestA>,但是您可以将List<TestA>的内容转储到List<TestB>。试试下面的方法:

List<TestA> result = new List<TestA>();
List<TestB> data = new List<TestB>();
result.addAll(data);

我没有尝试过这段代码,所以可能有错误,但其思想是,它应该遍历数据对象,将元素(TestB对象)添加到List中。我希望这对你有用。

其他回答

泛型的强制转换是不可能的,但是如果你以另一种方式定义列表,则可以将TestB存储在其中:

List<? extends TestA> myList = new ArrayList<TestA>();

在使用列表中的对象时,仍然需要进行类型检查。

您可以在Eclipse Collections中使用selectInstances方法。这将涉及创建一个新的集合,但不会像使用强制转换的公认解决方案那样有效。

List<CharSequence> parent =
        Arrays.asList("1","2","3", new StringBuffer("4"));
List<String> strings =
        Lists.adapt(parent).selectInstancesOf(String.class);
Assert.assertEquals(Arrays.asList("1","2","3"), strings);

我在示例中加入StringBuffer是为了说明selectInstances不仅向下转换类型,而且还将过滤集合是否包含混合类型。

注意:我是Eclipse Collections的提交者。

当您强制转换对象引用时,您只是强制转换引用的类型,而不是对象的类型。强制转换不会改变对象的实际类型。

Java没有转换对象类型的隐式规则。(与原语)

相反,您需要提供如何将一种类型转换为另一种类型并手动调用它。

public class TestA {}
public class TestB extends TestA{ 
    TestB(TestA testA) {
        // build a TestB from a TestA
    }
}

List<TestA> result = .... 
List<TestB> data = new List<TestB>();
for(TestA testA : result) {
   data.add(new TestB(testA));
}

这比在有直接支持的语言中更冗长,但它是可行的,您不需要经常这样做。

在Java 8中,实际上可以做到

List<TestB> variable = collectionOfListA
    .stream()
    .map(e -> (TestB) e)
    .collect(Collectors.toList());

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.