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