我正在探索Java,在尝试类型转换时,我遇到了以下问题,当我第一次调用该方法时,转换失败了,但在构造列表后,它工作得很好。
寻找一个明确的解释,请:)由于
import java.util.*;
import java.util.Set;
import java.util.HashMap; // import the HashMap class
public class Main{
public static void main(String[] args)
{
Set<Map<String, ?>> rows = new HashSet();
HashMap<String, String> map = new HashMap<String, String>();
map.put("1","one");
map.put("2","two");
HashMap<String, String> mapp = new HashMap<String, String>();
mapp.put("3","three");
mapp.put("4","four");
rows.add(map);
rows.add(mapp);
//WHY THE FOLLOWING DOESN'T WORK ?????
//printItems((List<Map<String, ?>>) rows);
//BUT THE FOLLOWING WORKS FINE
List<Map<String, ?>> listedRows = new ArrayList<>(rows);
printItems(listedRows);
}
public static void printItems(List<Map<String, ?>> items) {
for (Map<String, ?> str: items)
System.out.println(str);
}
}
不能工作,因为rows
的运行时类型是HashSet
,HashSet
不实现List
接口。
当你创建listedRows
时,它可以工作,因为该对象的运行时类型是ArrayList
,它实现了List
接口。
在您的示例中,您可以只在printItems
中使用Collection
抽象,因为您所需要做的就是遍历项。这将允许您使用Set
或List
(或任何其他Collection
)调用该方法,而无需强制转换或重新创建对象。
public static void printItems(Collection<Map<String, ?>> items) {
for (Map<String, ?> str: items)
System.out.println(str);
}
如果你感兴趣的话:
强制类型转换通常只在下列情况下起作用:编译时类型的对象是运行时类型的父类,并且需要将对象的编译时类型强制转换为运行时类型,以便调用特定于运行时类型的方法。
例如:
public void addTenObjects(List l) {
if (l instanceof ArrayList)
((ArrayList)l).ensureCapacity(10)
for (int i = 0; i < 10; i++)
l.add(new Object())
}
Set
和List
接口都扩展了Collection
,但它们之间不相互扩展。也就是说,它们是同胞,因此你不能通过强制转换将一个转换为另一个。
由于您的方法printItems
只是打印传入它的参数的内容,您可以使用Java 8Iterable.forEach()
代替它,它期望一个Consumer
表示动作:
rows.forEach(System.out::println);
不需要类型强制转换或复制任何东西,当您有一个相当简单的逻辑(如本例)时,也不需要引入该方法。