如何在接口中使用静态方法返回实例方法返回的泛型实例?

时间:2017-05-02 00:35:26

标签: java generics java-8

很抱歉标题的措辞难以理解。我此刻正在摸索着言语。 :)

我有一堆不同的实体从数据存储中出来,并且它们在运行时通过搜索链接在一起。当我需要检索其中一个时,我有类或类名,我有找到它所需的搜索文本。

我希望能够声明如何在自己的类中搜索每个对象的详细信息,但是如果请求搜索的代码不知道实际类型(即Foo.class),那么它会调用静态方法来处理搜索设置。 现在,我必须施放和压制警告,并不觉得应该需要这样做。我错过了一些简单的东西吗?

public interface RetrievableBySearch<E extends RetrievableBySearch> extends Retrievable {
  E searchForEntity(String searchKey);

  @SuppressWarnings("unchecked")
  static <E extends RetrievableBySearch> E getEntityBySearch(Class<E> entityClass, String searchKey) {
    try {
      return (E) entityClass.newInstance().searchForEntity(searchKey);
    } catch (ReflectiveOperationException e) {
      throw new IllegalArgumentException("Unable to instantiate entityClass", e);
    }
  }
}

public class Foo implements RetrievableBySearch<Foo> {
  @Override public Foo searchForEntity(String searchKey) {
    // Do a search...
    return new Foo();
  }
}

// Elsewhere, someone has a reference to a Class<Foo>
Retrievable thing = RetrievableBySearch.getEntityBySearch(getClassForThing(), "Find this");

2 个答案:

答案 0 :(得分:4)

您使用RetrievableBySearch作为原始类型。如果只提供类型参数,则不需要强制转换:

interface RetrievableBySearch<E extends RetrievableBySearch<E>> {
    E searchForEntity(String searchKey);

    static <E extends RetrievableBySearch<E>> E getEntityBySearch(Class<E> entityClass,
            String searchKey) {
        try {
            return entityClass.newInstance().searchForEntity(searchKey);
        } catch (ReflectiveOperationException e) {
            throw new IllegalArgumentException("Unable to instantiate entityClass", e);
        }
    }
}

答案 1 :(得分:2)

首先,在回答您的问题时,您可以避免取消选中警告,如果您更换&lt; E扩展了RetrievableBySearch&gt;在两个地方都有&lt; E扩展了RetrievableBySearch&lt; E>取代。

那就是说,我应该指出这个类的语义是非常可疑的。 searchForEntity方法建议界面可能被命名为“Searcher”,而不是“RetreivableBySearch”。 “RetreivableBySearch”听起来根本不像接口名称,因为这意味着其他类必须满足与搜索相关的合同。如果你想通过类名和searchKey查找一个对象,我建议你制作一个classname / searchKey元组的地图。