在类型为T的泛型类中,如果T为List <e>,如何查找E

时间:2016-03-07 12:32:14

标签: java generics

我有一个用T参数化的泛型类。它包含T类型的数据,并且有一些使用类型T的方法。但是,如果 T恰好是List<E>,我希望能够编写一种方法,我可以使用此E作为类型,但我不确定是否有办法做到这一点。

举个例子,考虑一下:

class Test<T> {
  private T data;
  public void setData(T t) {data = t;}
  public T getData() { return data; }
}

现在假设这被实例化为Test<List<String>>。所以我们有一个getData方法的对象返回List<String>。在这个对象上,我想像setCallback这样的方法采用类似Callback<String>的方法。换句话说,我需要一个方法,将参数化为E的接口作为参数,其中ET中的List<E> == T相关。

我该如何编写此方法?

请注意,我希望T强制List成为T。在类级别上将List<E>声明为Test<Integer>,必须同时使用Test<List<String>>setCallback类,但仅在后一种情况下才应使用interface AbstractCallback<T> {} interface Callback<E> extends AbstractCallback<List<E>> { void onSomethingHappened(E e); } class Test<T> { ... void setCallback(AbstractCallback<T> callback); } 方法有意义。

我最接近的是:

Test<List<String>> test = new Test<>();
test.setCallback(new Callback<String>() {
  public void onSomethingHappened(String e) {}
});

关于这一点,我可以做到

Callback

这是有效的,如果T 一个列表,我根本无法创建一个拟合Callback(因为它根本不可能)创建实现AbstractCallback<T>的{​​{1}}实例,除非T是List。然而,被迫使用setCallback方法采用抽象超类(实际上是接口)而不是更具体的方法会使界面不清楚并且有些模糊。

我还考虑将setCallback放在Test的子类上,使class SubTest<E> extends Test<List<E>>,但这意味着我必须实例化此类而不是Test,即使我委托构造对于Test个对象到工厂,T的类型在构造时是未知的(除非我添加Class个参数来携带类型信息,我不愿意) - 只有在调用setData后才会知道。此外,我更喜欢如果客户只需要引用Test而不打算使用压缩等等。

最后,我考虑过让客户端负责提供正确的类型,只需将E定义为与T无关的未绑定泛型类型,并简单地让不正确的调用导致ClassCastExceptions:< / p>

<E> void setCallback(Callback<E> callback);

有更好的方法吗?为了重新限制,基本上我想要声明一个泛型方法,其泛型类型E与类相关&#39;通用类型T,以便T等同于List<E>;理想情况下,如果T根本不是 一个List,则无法调用该方法。所以你可以说这是{em>相反有一个E类,并用List<E><T extends List<E>>声明一个方法。 我想这可能是不可能的,因为在编译时没有办法判断T是否是List,但也许有一种比我上面的建议更聪明的方法呢?

2 个答案:

答案 0 :(得分:4)

我不确定您是否要强制T成为列表。如果这样做,您可以使用两个泛型类型参数 - 一个用于元素,另一个用于List

class Test<E,T extends List<E>> {
  private T data;
  public void setData(T t) {data = t;}
  public T getData() { return data; }
}

现在您可以在Test中编写使用E的方法。例如:

public E getFirst ()
{
    if (data != null && data.size() > 0)
        return data.get(0);
     else
        return null;
}

或者你可以消除T并只使用E:

class Test<E> {
  private List<E> data;
  public void setData(List<E> t) {data = t;}
  public List<E> getData() { return data; }
}

答案 1 :(得分:-2)

只需提供方法通用参数:

public <K extends List<T>> void setData(K t) {
  data = t;
}

使用示例:

 objRef.setData(new ArrayList<Integer>());

此方法强制您作为参数传递绑定到类的 T 类型列表。