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));
}
/**
* Filter the given list, and create a new list that only contains
* the elements that are (subtypes) of the class c
*
* @param listA The input list
* @param c The class to filter for
* @return The filtered list
*/
private static <T> List<T> filter(List<?> listA, Class<T> c)
{
List<T> listB = new ArrayList<T>();
for (Object a : listA)
{
if (c.isInstance(a))
{
listB.add(c.cast(a));
}
}
return listB;
}
此方法可用于过滤任意列表(不仅具有与类型参数相关的给定子类型-超类型关系),如本例所示:
// A list of type "List<Number>" that actually
// contains Integer, Double and Float values
List<Number> mixedNumbers =
new ArrayList<Number>(Arrays.asList(12, 3.4, 5.6f, 78));
// Filter the list, and create a list that contains
// only the Integer values:
List<Integer> integers = filter(mixedNumbers, Integer.class);
System.out.println(integers); // Prints [12, 78]
17条答案
按热度按时间lp0sw83n1#
非常奇怪的是,一些工具箱仍然没有提供手动转换列表的功能,例如:
当然,这不会逐个检查项,但这正是我们要避免的,如果我们知道我们的实现只提供子类型的话。
pengsaosao2#
我觉得你选错了方向。。。如果方法返回
TestA
物体,那么把它们扔到TestB
.基本上,您要求编译器允许您执行
TestB
对类型的操作TestA
这不支持他们。11dmarpk3#
这是可能的,因为类型擦除。你会发现的
在内部,两个列表都是
List<Object>
. 因为这个原因,你不能把一个投给另一个-没有什么可以投的。daupos2t4#
如果你有一个类的对象
TestA
,你不能把它投给TestB
. 每TestB
是一个TestA
,但不是相反。在以下代码中:
第二行会抛出一个
ClassCastException
.你只能投一个
TestA
如果对象本身是TestB
. 例如:所以,你不一定要列出
TestA
一份TestB
.rseugnpd5#
你真的不能:
示例取自本java教程
假设有两种类型
A
以及B
以至于B extends A
. 则以下代码正确:前面的代码有效,因为
B
是的一个子类A
. 现在,你怎么办List<A>
以及List<B>
?事实证明
List<B>
不是的子类List<A>
因此我们不能写作而且,我们甚至不会写字
List<A>
以及List<B>
:List<?>
例如。以下内容有效:然而,你会得到一个警告。可以通过添加
@SuppressWarnings("unchecked")
你的方法。l0oc07j26#
这应该管用
vuktfyat7#
转换泛型是不可能的,但是如果您以另一种方式定义列表,则可以在其中存储testb:
在使用列表中的对象时,仍然需要进行类型检查。
jrcvhitl8#
简单地铸造
List<TestB>
几乎可以工作;但它不起作用,因为不能将一个参数的泛型类型强制转换为另一个参数。但是,您可以强制转换中间通配符类型,这是允许的(因为您可以在通配符类型之间进行强制转换,只需要一个未选中的警告):gajydyqb9#
这个测试展示了如何铸造
List<Object>
至List<MyClass>
. 但你要注意这一点objectList
必须包含与相同类型的示例MyClass
. 这个例子可以在List<T>
已使用。为此,获取字段Class<T> clazz
在构造函数中,并使用它而不是MyClass.class
.wlwcrazw10#
最好的安全方法是实施
AbstractList
并在实现中转换项。我创造了ListUtil
助手类:你可以用
cast
一种在列表中盲目投射对象的方法convert
安全铸造方法。例子:jdg4fx2g11#
你不能施法
List<TestB>
至List<TestA>
正如steve kuo提到的,但是你可以把List<TestA>
进入List<TestB>
. 请尝试以下操作:我没有尝试过这段代码,所以可能会有错误,但我的想法是它应该遍历数据对象,将元素(testb对象)添加到列表中。我希望这对你有用。
gstyhher12#
当您强制转换对象引用时,您只是强制转换引用的类型,而不是对象的类型。强制转换不会更改对象的实际类型。
java没有用于转换对象类型的隐式规则(与基本体不同)
相反,您需要提供如何将一种类型转换为另一种类型并手动调用它。
这比直接支持的语言更冗长,但它可以工作,您不需要经常这样做。
zpjtge2213#
我知道的唯一方法就是复制:
1bqhqjot14#
使用Java8,您实际上可以
mzmfm0qo15#
由于这是一个被广泛引用的问题,并且当前的答案主要解释了为什么它不起作用(或者提出了我永远不希望在产品代码中看到的骇人的、危险的解决方案),所以我认为应该添加另一个答案,显示陷阱和可能的解决方案。
在其他答案中已经指出了这种转换通常不起作用的原因:转换是否真正有效取决于原始列表中包含的对象的类型。当列表中的对象的类型不是
TestB
,但属于TestA
,则强制转换无效。当然,演员阵容可能是有效的。您有时会得到编译器不可用的类型信息。在这些情况下,可以强制转换列表,但通常不建议:
一个人可以。。。
... 投下整个名单或
... 强制转换列表的所有元素
第一种方法(对应于目前公认的答案)的含义是微妙的。乍一看,它似乎工作正常。但是如果输入列表中有错误的类型,那么
ClassCastException
将被抛出,可能在代码中的一个完全不同的位置,并且可能很难对此进行调试并找出错误元素滑入列表的位置。最糟糕的问题是,有人甚至可能在列表被强制转换后添加无效元素,这使得调试更加困难。调试这些伪代码的问题
ClassCastExceptions
可以缓解Collections#checkedCollection
方法家族。基于类型筛选列表
一种更安全的从
List<Supertype>
到List<Subtype>
实际上是过滤列表,并创建一个只包含具有特定类型的元素的新列表。这种方法的实施有一定的自由度(例如,关于null
条目),但一种可能的实现可能如下所示:此方法可用于过滤任意列表(不仅具有与类型参数相关的给定子类型-超类型关系),如本例所示: