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

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

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

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

您可以将任何对象先转换为Object,然后将其转换为任何types。 在你的情况下:

 (List<Customer>)(Object)list; 

您必须确保在运行时该列表除了包含Customer对象外没有任何内容。

批评者说,这样的投射表明你的代码有问题; 你应该能够调整你的types声明来避免它。 但是Javagenerics太复杂了,并不完美。 有时候,你只是不知道是否有一个漂亮的解决scheme来满足编译器的要求,即使你非常了解运行时types,而且你知道你所要做的是安全的。 在这种情况下,只要按照需要进行粗铸,就可以把工作留给家里。

这是因为虽然客户是一个对象,客户列表不是对象列表。 如果是这样,那么你可以把任何对象放在客户列表中。

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

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

要么

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

但是请记住,不build议这样不加控制的强制转换。

您可以使用双重播放。

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

使用Java 8 Streams :

有时蛮力铸造是好的:

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

但是,这是一个更通用的解决scheme:

 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()); 

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

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

转换意味着你得到一个新的列表对象,但是你说铸造,这意味着你想临时对待一个对象作为另一种types。

这是这个问题。

如果允许以下情况会发生什么(注意,我假设在投射之前,对象列表实际上只包含Customer对象,否则即使在这个假想的Java版本中投射也不起作用):

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

在这种情况下,这会试图将一个不是客户的对象看作是一个客户,并且会在列表中或者从任务中得到一个运行时错误。

generics,但是,应该给你types安全的数据types,如集合,因为他们喜欢扔“保证”一词,这种types的演员,随之而来的问题,是不允许的。

在.NET 4.0中(我知道,你的问题是关于java的),这将被允许在一些非常特殊的情况下 ,编译器可以保证你所做的操作是安全的,但是从一般意义上讲,这种types的转换不会被)允许。 对于java来说也是一样,尽pipe我不确定是否有任何计划将Java语言和Java语言混为一谈。

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

您应该遍历列表并逐个投射所有对象

你不能因为List<Object>List<Customer>不在同一个inheritance树中。

您可以添加一个新的构造函数到您的List<Customer>类中,它接受一个List<Object> ,然后遍历列表将每个Object投射到一个Customer并将其添加到您的集合中。 请注意,如果调用者的List<Object>包含非Customer某个东西,则可能会发生无效的转换exception。

generics列表的要点是将它们限制到某些types。 您正在尝试列出可以包含任何内容的订单(订单,产品等),并将其列入只能带客户的列表。

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

正如其他人指出的那样,由于List<Object>不是List<Customer> ,所以不能保存转换。 你可以做的是在列表中定义一个视图,进行就地types检查。 使用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. } }); 

根据您想要对列表执行什么操作,您甚至可能不需要将其转换为List<Customer> 。 如果您只想将Customer对象添加到列表中,则可以如下声明它:

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

这是合法的(好吧,不仅仅是合法的,而且是正确的 – 这个列表是“给客户的一些超types”),如果你打算把它传递给一个仅仅添加对象到列表中的方法,那么上面的通用边界就足够了。

另一方面,如果你想从列表中检索对象,并将它们强制input为Customers,那么你的运气不好,这是正确的。 因为列表是一个List<Object>所以不能保证内容是客户,所以你必须提供你自己的检索。 (或者真的,绝对的,加倍确定列表将只包含Customers并使用来自其他答案之一的双重播放,但要意识到,你完全规避了编译时types – 从generics中获得的安全性这个案例)。

从广义的angular度来说,考虑写一个方法时可以接受的最广泛的generics边界总是好的,如果将要被用作库方法,则是双倍的。 如果你只是要从列表中读取,使用List<? extends T> List<? extends T>而不是List<T> ,这使得调用者可以传入更多的参数,这意味着他们不太可能遇到类似于这里的可避免的问题。

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

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

是。 它会将您的列表投入您所要求的genericstypes。

在上面给出的情况下,你可以做一些这样的代码:

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

不是最有效的方法,但是:

  List<Customer> customers = new ArrayList<Customers>(getList()); 

另一种方法是使用Java 8stream。

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

您可以创build一个新的列表并添加元素:

例如:

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

你可以做这样的事情

 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;