如何将List <object>转换为List <myclass> </myclass> </object>

时间:2009-12-16 21:23:11

标签: java generics casting

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

 ...
  List<Object> list = getList();
  return (List<Customer>) list;

编译器说:无法将List<Object>投射到List<Customer>

17 个答案:

答案 0 :(得分:135)

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

(List<Customer>)(Object)list; 

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

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

答案 1 :(得分:36)

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

答案 2 :(得分:33)

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

List<? extends Object> list = getList();
return (List<Customer>) list;

List list = getList();
return (List<Customer>) list;

但请注意,不建议不要进行此类未经检查的演员表。

答案 3 :(得分:21)

你可以使用双重演员。

return (List<Customer>) (List) getList();

答案 4 :(得分:15)

使用Java 8 Streams

有时蛮力铸造很好:

List<MyClass> mythings = (List<MyClass>) (Object) objects

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

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

List<String> strings = list.stream()
                       .map(element->(String) element)
                       .collect(Collectors.toList());

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

list.stream()
    .filter(element->element instanceof String)
    .map(element->(String)element)
    .collect(Collectors.toList());

答案 5 :(得分:8)

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

我们假设你被允许施放。注意,我说 cast ,因为这就是你所说的,但有两种操作是可能的,投射转换

转换意味着您获得了一个新的列表对象,但是您说要转换,这意味着您要暂时将一个对象视为另一种类型。

这就是问题所在。

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

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

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

然而,泛型应该为你提供类型安全的数据类型,比如集合,并且由于他们喜欢抛出“保证”这个词,所以不允许这种类型的强制转换,以及随之而来的问题。 / p>

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

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

答案 6 :(得分:3)

您应该遍历列表并逐个转换所有对象

答案 7 :(得分:3)

你可以做这样的事情

List<Customer> cusList = new ArrayList<Customer>();

for(Object o: list){        
    cusList.add((Customer)o);        
}

return cusList; 

或Java 8方式

list.stream().forEach(x->cusList.add((Customer)x))

return cuslist;

答案 8 :(得分:2)

您不能因为List<Object>List<Customer>不在同一继承树中。

您可以在List<Customer>课程中添加一个新的构造函数,该List<Object>类将Object添加Customer,然后遍历列表,将每个List<Object>投射到Customer并将其添加到您的{{1}}采集。请注意,如果来电者的{{1}}包含的内容不是{{1}},则可能会发生无效的强制转换异常。

通用列表的要点是将它们约束为某些类型。您正试图获取一个可以包含任何的列表(订单,产品等),然后将其压缩到只能吸引客户的列表中。

答案 9 :(得分:1)

最好的办法是创建一个新的List<Customer>,遍历List<Object>,将每个项目添加到新列表中,然后返回。

答案 10 :(得分:1)

正如其他人所指出的那样,你无法保存它们,因为List<Object>不是List<Customer>。你可以做的是在列表上定义一个进行就地类型检查的视图。使用Google Collections即:

return Lists.transform(list, new Function<Object, Customer>() {
  public Customer apply(Object from) {
    if (from instanceof Customer) {
      return (Customer)from;
    }
    return null; // or throw an exception, or do something else that makes sense.
  }
});

答案 11 :(得分:1)

根据您要对列表执行的操作,您甚至可能不需要将其强制转换为List<Customer>。如果您只想将Customer个对象添加到列表中,可以按如下方式声明:

...
List<Object> list = getList();
return (List<? super Customer>) list;

这是合法的(好吧,不仅仅是合法的,而且正确的 - 列表是“客户的某种超类型”),如果你要将它传递给一个方法,只是将对象添加到列表中,然后上面的通用边界就足够了。

另一方面,如果你想从列表中检索对象并强烈输入它们作为客户 - 那么你运气不好,这是正确的。由于列表是List<Object>,因此无法保证内容是客户,因此您必须在检索时提供自己的转换。 (或者,确实,绝对,双重确保列表只包含Customers并使用其他答案之一的双重转换,但确实意识到你完全绕过编译时类型安全你在这种情况下从泛型获得。)

从广义上讲,考虑在编写方法时可接受的最广泛的通用边界总是好的,如果将它用作库方法则更是如此。如果您只是要从列表中读取,请使用List<? extends T>而不是List<T>,这会让您的调用者在他们可以传递的参数范围内更多并且意味着他们不太可能遇到类似于你在这里的可避免的问题。

答案 12 :(得分:1)

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

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

答案 13 :(得分:0)

最简单的解决方案是使用

(((List<Object>)(List<?>) yourCustomClassList))

答案 14 :(得分:0)

您可以创建一个新列表并向其添加元素:

例如:

List<A> a = getListOfA();
List<Object> newList = new ArrayList<>();
newList.addAll(a);

答案 15 :(得分:0)

与上面的Bozho相似。你可以通过这种方法在这里做一些解决方法(虽然我自己不喜欢它):

public <T> List<T> convert(List list, T t){
    return list;
}

是。它会将您的列表转换为您要求的通用类型。

在上面的给定案例中,您可以执行以下代码:

    List<Object> list = getList();
    return convert(list, new Customer());

答案 16 :(得分:-1)

List<Object[]> testNovedads = crudService.createNativeQuery(
            "SELECT ID_NOVEDAD_PK, OBSERVACIONES, ID_SOLICITUD_PAGO_FK FROM DBSEGUIMIENTO.SC_NOVEDADES WHERE ID_NOVEDAD_PK < 2000");

Convertir<TestNovedad> convertir = new Convertir<TestNovedad>();
Collection<TestNovedad> novedads = convertir.toList(testNovedads, TestNovedad.class);
for (TestNovedad testNovedad : novedads) {
    System.out.println(testNovedad.toString());
}

public Collection<T> toList(List<Object[]> objects, Class<T> type) {
    Gson gson = new Gson();
    JSONObject jsonObject = new JSONObject();
    Collection<T> collection = new ArrayList<>();
    Field[] fields = TestNovedad.class.getDeclaredFields();
    for (Object[] object : objects) {
        int pos = 0;
        for (Field field : fields) {
            jsonObject.put(field.getName(), object[pos++]);
        }
        collection.add(gson.fromJson(jsonObject.toString(), type));
    }
    return collection;
}