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

这不能汇编,任何建议都可以。

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

编译器说: 不能将 List<Object>转换为 List<Customer>

266296 次浏览

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

您只需迭代该列表并逐个强制转换所有对象

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

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

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

或者

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

但是请记住,不建议进行这种未检查的强制类型转换。

请注意,我不是 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];

在这种情况下,这会尝试将一个不是客户的对象视为客户,并且您会在某个时刻得到一个运行时错误,要么是列表内的表单,要么是来自赋值。

但是,泛型应该提供类型安全的数据类型,比如集合,而且由于它们喜欢使用“保证”这个词,所以不允许进行这种类型转换,以及随后出现的问题。

进去。NET 4.0(我知道,你的问题是关于 Java) ,这将是允许的 在某些特定的情况下,编译器可以保证你做的操作是安全的,但在一般意义上,这种类型的强制转换将不被允许。Java 也是如此,尽管我不确定是否有计划引入协变和逆变到 Java 语言中。

希望比我更了解 Java 的人能够告诉你 Java 未来或实现的细节。

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

您可以向 List<Customer>类添加一个新的构造函数,该构造函数接受一个 List<Object>,然后循环遍历列表,将每个 Object强制转换为一个 Customer,并将其添加到集合中。请注意,如果调用方的 List<Object>包含不是 Customer的内容,则可能发生无效的强制转换异常。

泛型列表的要点是将它们约束为某些类型。您试图获取一个可以包含 什么都行的列表(订单、产品等) ,并将其压缩到一个只能接受客户的列表中。

您总是可以通过将任何对象向上强制转换为对象来将其转换为任何类型。在您的情况下:

(List<Customer>)(Object)list;

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

批评者认为,这种强制转换表明代码有问题; 您应该能够调整类型声明以避免这种情况。但是 Java 泛型太复杂了,它并不完美。有时候,即使您非常清楚运行时类型,并且知道您正在尝试做的事情是安全的,您也不知道是否有满足编译器的完美解决方案。在这种情况下,只需要根据需要进行粗略的铸造,这样您就可以把工作留在家里。

正如其他人指出的那样,你不能保险地施放它们,因为 List<Object>不是 List<Customer>。您可以做的是在列表中定义一个视图,它执行就地类型检查。使用 谷歌收藏将会是:

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.
}
});

与上面的 Bozho 类似,你可以通过这个方法在这里做一些工作(尽管我自己不喜欢它) :

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

是的。它会将您的列表强制转换为所需的泛型类型。

在上面给定的情况下,您可以执行以下代码:

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

你可以使用双重石膏。

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

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

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

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

另一方面,如果您想从列表中检索对象并将其强类型化为 Customer,那么您就不走运了,而且这样做是正确的。因为列表是 List<Object>,所以不能保证内容是客户,所以您必须在检索时提供自己的强制类型转换。(或者真的,绝对,双重确定列表将只包含 Customers,并使用来自其他答案之一的双转换,但是要意识到,在这种情况下,您完全绕过了从泛型获得的编译时类型安全)。

从广义上讲,在编写方法时考虑可接受的最广泛的泛型边界总是有好处的,如果要将其用作库方法,更要考虑这一点。例如,如果你只读一个列表,使用 List<? extends T>而不是 List<T>——这给了你的调用者 很多更大的范围,他们可以传递参数,这意味着他们不太可能遇到类似你在这里遇到的可以避免的问题。

使用 Java8小溪:

有时蛮力铸造也不错:

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

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

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


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

这样做有很多好处,但其中之一是,如果你不确定你的列表包含什么内容,你可以更优雅地列出它:

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

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

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

您可以创建一个新的 List 并将元素添加到其中:

例如:

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;
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;
}

最简单的解决办法就是

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