【问题标题】:Stream return class type generic流返回类类型泛型
【发布时间】:2021-08-30 05:20:25
【问题描述】:

我有一个这样的列表

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
}

【问题讨论】:

  • “类类型”是什么意思?
  • @chrylis-cautiouslyoptimistic- 我在帖子示例中解释了当我确实 findHouse("third") 我希望它返回 House.WithoutPlace 而不是 House
  • 它没有返回 either;它返回Houseinstances(在本例中为House.WithoutPlace 的实例)。实例House.WithoutPlace 的实例。 (如果您尝试更改返回 type,它不会那样工作,除非您 传入 Class&lt;T&gt; 并过滤两次。)

标签: java guava


【解决方案1】:

你根本不能这样做,除非你知道在代码中的特定位置你期望哪种类型的房子。

修改后的方法将为您提供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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-24
    • 2014-02-11
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多