[英]On a generic class of type T, how to find E if T is List<E>
I have a generic class parameterized with T
. 我有一个用
T
参数化的泛型类。 It holds data of type T
and has a few methods using type T
. 它包含
T
类型的数据,并且使用类型T
有一些方法。 However, if T
happens to be a List<E>
, I'd like to be able to write a method where I can use this E
as a type, but I'm not sure if there's a way to do that. 但是, 如果
T
恰好是List<E>
,我希望能够编写一个方法,我可以将此E
用作类型,但我不确定是否有办法做到这一点。
As an example, consider this: 举个例子,考虑一下:
class Test<T> {
private T data;
public void setData(T t) {data = t;}
public T getData() { return data; }
}
Now imagine this is instantiated as Test<List<String>>
. 现在假设这被实例化为
Test<List<String>>
。 So we have an object with a getData
method returning a List<String>
. 所以我们有一个带有
getData
方法的对象返回一个List<String>
。 On this object I would like to also have a method like setCallback
taking something like Callback<String>
. 在这个对象上我想有一个像
setCallback
这样的方法,比如Callback<String>
。 In other words, I need a method taking as its argument an interface parameterized with E
where E
relates to T
as in List<E> == T
. 换句话说,我需要一种方法以作为它的参数的接口参数化
E
其中E
涉及T
如List<E> == T
。
How can I write this method? 我该怎么写这个方法?
Note that I do not want to force T
into being a List
by eg declaring T
as List<E>
on a class level, it must be possible to use the class both Test<Integer>
and Test<List<String>>
, but only in the latter case should the setCallback
method make sense. 请注意,我不想强迫
T
形成了一个List
例如通过声明T
的List<E>
上一流水平,它必须能够使用的类都Test<Integer>
和Test<List<String>>
,但只有在后一种情况下, setCallback
方法才有意义。
The closest thing I've come up with is this: 我最接近的是:
interface AbstractCallback<T> {}
interface Callback<E> extends AbstractCallback<List<E>> {
void onSomethingHappened(E e);
}
class Test<T> {
...
void setCallback(AbstractCallback<T> callback);
}
On this, I can do 在这方面,我能做到
Test<List<String>> test = new Test<>();
test.setCallback(new Callback<String>() {
public void onSomethingHappened(String e) {}
});
This works, and if T is not a List I won't be able to create a fitting Callback
, as desired (since it's simply not possible to create an instance of Callback
that implements AbstractCallback<T>
unless T
is a List). 这是有效的,如果T 不是 List,我将无法根据需要创建适合的
Callback
(因为除非T
是List,否则根本无法创建实现AbstractCallback<T>
的Callback
实例)。 However, being forced to have the setCallback
method take the abstract super-class (interface actually) rather than the more concrete one makes the interface unclear and somewhat ambigious. 然而,被迫使用
setCallback
方法采用抽象超类(实际上是接口)而不是更具体的方法使得界面不清楚并且有点模糊。
I have also considered placing setCallback
on a sub-class of Test such that class SubTest<E> extends Test<List<E>>
but this means I have to instantiate this class instead of Test
, and even if I delegate construction of Test
objects to a factory, the type of T
is not known at time of construction (unless I add Class
arguments to carry type information, which I'd rather not) - it will only be known after setData
has been called. 我还考虑将
setCallback
放在Test的子类上,使得class SubTest<E> extends Test<List<E>>
但这意味着我必须实例化此类而不是Test
,即使我委托Test
对象的构造对于工厂来说, T
的类型在构造时是未知的(除非我添加Class
参数来携带类型信息,我宁愿不这样做) - 只有在调用setData
之后才会知道它。 Also, I prefer if clients only have to refer to Test
and not bother with down-casting etc. 此外,我更喜欢如果客户只需要参考
Test
而不打算使用压缩等。
Finally, I have considered just letting the client be responsible for supplying the correct type by just definining E
as an unbound generic type unrelated to T
, and simply let incorrect calls result in ClassCastExceptions: 最后,我考虑过让客户端负责提供正确的类型,只需将
E
为与T
无关的未绑定泛型类型,并简单地让不正确的调用导致ClassCastExceptions:
<E> void setCallback(Callback<E> callback);
Is there a better way of doing this? 有没有更好的方法呢? To re-cap, basically I want to declare a generic method with a generic type
E
related to the class' generic type T
so that T
is equivalent to List<E>
; 为了重新限制,基本上我想要声明一个泛型方法,该泛型方法具有与类'泛型类型
T
相关的泛型类型E
,因此T
等效于List<E>
; and, ideally, if T is not a List at all, the method is not possible to invoke. 理想情况下,如果T根本不是 List,则无法调用该方法。 So you could say this is the opposite of having a class of
E
and declaring a method with List<E>
or even <T extends List<E>>
. 所以你可以说这与一个
E
类相反 ,并用List<E>
或甚至<T extends List<E>>
声明一个方法。 I imagine it may not be possible since at compile-time there is no way to tell if T
is a List or not, but maybe there is a more clever way around it than my suggestion above? 我想这可能是不可能的,因为在编译时没有办法判断
T
是否是List,但也许有一个比我上面的建议更聪明的方法呢?
I'm not sure if you want to force T to be a List. 我不确定你是否想强迫T成为一个List。 If you do, you can use two generic type parameters - one for the element and another for the
List
: 如果这样做,您可以使用两个泛型类型参数 - 一个用于元素,另一个用于
List
:
class Test<E,T extends List<E>> {
private T data;
public void setData(T t) {data = t;}
public T getData() { return data; }
}
Now you can write methods in Test that use E. For example : 现在,您可以在Test中编写使用E的方法。例如:
public E getFirst ()
{
if (data != null && data.size() > 0)
return data.get(0);
else
return null;
}
Or you can eliminate T and just use E : 或者你可以消除T并只使用E:
class Test<E> {
private List<E> data;
public void setData(List<E> t) {data = t;}
public List<E> getData() { return data; }
}
Simply provide method generic parameters: 只需提供方法通用参数:
public <K extends List<T>> void setData(K t) {
data = t;
}
Example of usage: 用法示例:
objRef.setData(new ArrayList<Integer>());
This method enforces you to pass as an argument the list of type T which is bound to the class. 此方法强制您将绑定到类的类型T的列表作为参数传递。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.