Stream return class 类型泛型
Stream return class type generic
我有一个这样的列表
public static ImmutableList<House> HOUSES =
ImmutableList.of(
new House.WithName("first"),
new House.WithName("second"),
new House.WithoutPlace("third", 9400));
我有一种方法可以通过名字找到房子,但我想要它 return class 类型而不是房子界面,例如当我这样做时 findHouse("third")
我想要return House.WithoutPlace
而不是 House
,我该怎么做?
public static <T extends House> ImmutableList<T> findHouse(String name) {
return HOUSES.stream()
.filter(h -> h.name().equals(name))
.collect(toImmutableList());
// returns no instance(s) of type variable(s) exist
}
你根本不能这样做,除非你知道你在代码中的特定位置期望的房屋类型。
修改后的方法将为您提供 House
的单个子类型实例,假设您可以提供该房屋的 class 类型。
@SuppressWarnings("unchecked")
public static <T extends House> T findHouse(Class<T> type, String name) {
for (House house : HOUSES) {
if (type.isInstance(house) && house.name.equals(name)) {
return (T) house;
}
}
return null;
}
你的例子的问题是,在搜索时,你不能确定你会得到哪个实例(以及它是什么子类型)。编译器无法在编译时知道您将获得 House.WithName
还是 House.WithoutPlace
。因此它不能推导出,什么样的列表为return,而必须return一个House
的列表。当您从结果列表中提取实例时,您必须稍后通过检查实例来单独转换以处理不同的子类型:
// your orifinal findHouse
List<House> housesWithMyName = findHouse("myName");
for (House house : housesWithMyName) {
if (house instanceof House.WithName) {
House.WithName myHood = (House.WithName) house;
// ...do something with myHood.
}
}
或者您可以使用修改后的版本,但它只会 return 最多匹配名称和预期类型的一个实例,或者 null
如果不存在这样的房子。
最终,您也可以使用此版本,其中结果仍然是 List
(具有通用元素类型 T),它将仅包含匹配类型和名称的所有房屋。您现在可以确定,您只会得到任何 House.WithName
或 House.WithoutPlace
等
@SuppressWarnings("unchecked")
public static <T extends House> List<T> findHouse(Class<T> type, String name) {
List<T> result = new ArrayList<>();
for (House house : HOUSES) {
if (type.isInstance(house) && house.name.equals(name)) {
result.add((T) house);
}
}
return result;
}