如何将List <Object>转换为List <MyClass>

use*_*313 88 java generics casting

这不编译,任何建议表示赞赏.

 ...
  List<Object> list = getList();
  return (List<Customer>) list;
Run Code Online (Sandbox Code Playgroud)

编译器说:不能投List<Object>List<Customer>

irr*_*ble 142

您始终可以将任何对象转换为任何类型,方法是先将其向上转换为Object.在你的情况下:

(List<Customer>)(Object)list; 
Run Code Online (Sandbox Code Playgroud)

您必须确保在运行时列表中只包含Customer对象.

批评者说,这样的演员表明你的代码有问题; 你应该能够调整你的类型声明以避免它.但Java泛型太复杂了,并不完美.有时您只是不知道是否有一个非常好的解决方案来满足编译器,即使您非常了解运行时类型并且您知道您尝试做什么是安全的.在这种情况下,只需根据需要进行原油铸造,这样就可以将工作留在家中.

  • 这也需要`@SuppressWarnings("unchecked")`.请注意,您也可以向上转换为`(List)`而不是`(Object)`. (7认同)

Bri*_*new 36

这是因为虽然客户对象,但客户列表不是对象列表.如果是,那么您可以将任何对象放在客户列表中.

  • 不,不是.如果允许上述情况,您将绕过类型安全.请注意,强制转换并不意味着创建新列表并复制项目.它意味着将单个实例作为不同的类型处理,因此您将拥有一个包含潜在非Customer对象的列表,该对象具有不应该的类型安全保证.这与java无关.既然你觉得这个功能让Java在黑暗时代陷入困境,我向你挑战,解释你认为这应该如何运作. (2认同)
  • @BrainSlugs83 提出问题的人专门询问了铸造问题。如果 Java 还没有像您引用的 .NET 方法这样的相关方法(顺便说一下,它仍然没有转换),那么您应该可以轻松添加它们。不过,这与手头的问题有点正交,它询问了特定的语法。 (2认同)

Boz*_*zho 32

根据您的其他代码,最佳答案可能会有所不同.尝试:

List<? extends Object> list = getList();
return (List<Customer>) list;
Run Code Online (Sandbox Code Playgroud)

要么

List list = getList();
return (List<Customer>) list;
Run Code Online (Sandbox Code Playgroud)

但请记住,不建议不要进行此类未经检查的演员表.

  • -1 - 这是一个非常糟糕的习惯,除非你使用"未经检查"的注释,编译器仍然会抱怨它 (3认同)

Pet*_*rey 21

你可以使用双重演员.

return (List<Customer>) (List) getList();
Run Code Online (Sandbox Code Playgroud)


rou*_*dar 17

使用Java 8 Streams:

有时蛮力铸造很好:

List<MyClass> mythings = (List<MyClass>) (Object) objects
Run Code Online (Sandbox Code Playgroud)

但这是一个更通用的解决方案:

List<Object> objects = Arrays.asList("String1", "String2");

List<String> strings = objects.stream()
                       .map(element->(String) element)
                       .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

有很多好处,但有一个是如果你不能确定它包含什么,你可以更优雅地投射你的列表:

objects.stream()
    .filter(element->element instanceof String)
    .map(element->(String)element)
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

  • 不过,这更像是一个副本而不是演员阵容。 (2认同)

d0x*_*d0x 11

另一种方法是使用 java 8 流。

    List<Customer> customer = myObjects.stream()
                                  .filter(Customer.class::isInstance)
                                  .map(Customer.class::cast)
                                  .collect(toList());
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这个解决方案太漂亮了,使用方法参考 (3认同)
  • 没想到有人会向下滚动那么远:D (2认同)

ang*_*son 8

请注意,我不是java程序员,但在.NET和C#中,此功能称为逆变或协方差.我还没有深入研究过这些东西,因为它们是.NET 4.0中的新功能,我没有使用它,因为它只是测试版,所以我不知道这两个术语中的哪一个描述了你的问题,但让我描述一下技术问题.

我们假设你被允许演员.请注意,我说是演员,因为这就是你所说的,但有两种操作是可能的,即投射转换.

转换意味着你得到一个新的列表对象,但是你说要转换,这意味着你想暂时将一个对象视为另一种类型.

这是问题所在.

如果允许以下内容会发生什么(注意,我假设在强制转换之前,对象列表实际上只包含Customer对象,否则即使在这个假设的java版本中,强制转换也不会起作用):

List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];
Run Code Online (Sandbox Code Playgroud)

在这种情况下,这将尝试将对象(不是客户)视为客户,并且您将在列表内部或从分配中的某一点获得运行时错误.

然而,泛型应该为你提供类型安全的数据类型,比如集合,并且因为他们喜欢抛出"保证"这个词,所以不允许使用这种类型的演员,以及随后出现的问题.

在.NET 4.0中(我知道,你的问题是关于java),这将在一些非常特殊的情况下被允许,编译器可以保证你所做的操作是安全的,但在一般意义上,这种类型的强制转换不会被)允许.这同样适用于java,虽然我不确定是否有任何计划引入java语言的共同和逆转.

希望有比我更好的Java知识的人可以告诉你java未来或实现的具体细节.

  • Java的未来是...... Scala.说真的,那些将泛型引入Java的人开发了一种新的语言,它与Java模糊地相似,但实际上非常精通类型:一种非常彻底和一致的类型处理实现.我想没有人确切知道哪些Scala功能会回流到Java,以及什么时候. (3认同)