流返回类类型泛型



我有一个这样的列表

public static ImmutableList<House> HOUSES =
ImmutableList.of(
new House.WithName("first"),
new House.WithName("second"),
new House.WithoutPlace("third", 9400));

和我有一个方法来找到一个房子的名字,但我希望它返回类类型不是房子的接口,例如,当我做findHouse("third")我希望它返回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的单个子类型实例,假设您可以提供该房屋的类类型。

@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。因此,它不能推断返回什么样的列表,必须返回一个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.
}
}

或者您可以使用修改后的版本,但它最多只返回一个匹配名称和期望类型的实例,如果不存在这样的房子,则返回null

最终,您也可以使用这个版本,其中结果仍然是List(具有泛型元素类型T),它将只包含任何类型和名称都匹配的房屋。你现在可以确定,你只得到任何House.WithNameHouse.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;
}

最新更新