我有一个用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
的接口作为参数,其中E
与T
中的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,但也许有一种比我上面的建议更聪明的方法呢?
答案 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 类型列表。