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

举个例子,考虑一下:

class Test {
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相关,如在列表< E>中. == T.

我该怎么写这个方法?

请注意,我不想强迫T成为List,例如将T声明为List< E>在类级别上,必须可以使用类Test< Integer>和测试< List< String>>,但仅在后一种情况下,setCallback方法才有意义.

我最接近的是:

interface AbstractCallback {}
interface Callback extends AbstractCallback> {
void onSomethingHappened(E e);
}
class Test {
...
void setCallback(AbstractCallback callback);
}

在这方面,我能做到

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

这是有效的,如果T不是List,我将无法根据需要创建适合的Callback(因为除非T是List,否则根本无法创建实现AbstractCallback< T>的Callback实例).然而,被迫使用setCallback方法采用抽象超类(实际上是接口)而不是更具体的方法使得界面不清楚并且有点模糊.

我还考虑将setCallback放在Test的子类上,使得类SubTest< E>扩展测试< List< E>>但这意味着我必须实例化此类而不是Test,即使我将Test对象的构造委托给工厂,在构造时T的类型也是未知的(除非我添加Class参数来携带类型信息,我’d而不是) – 只有在调用了setData之后才能知道它.此外,我更喜欢如果客户只需要参考测试而不打算使用压缩等.

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

void setCallback(Callback callback);

有没有更好的方法呢?为了重新限制,基本上我想要声明一个泛型方法,该泛型方法具有与类’泛型类型T相关的泛型类型E,因此T等效于List< E&gt ;;理想情况下,如果T根本不是List,则无法调用该方法.所以你可以说这与一个E类相反,并用List< E>声明一个方法.甚至< T extends List< E>>.

我想这可能是不可能的,因为在编译时没有办法判断T是否是List,但也许有一个比我上面的建议更聪明的方法呢?

最佳答案 我不确定你是否想强迫T成为一个List.如果这样做,您可以使用两个泛型类型参数 – 一个用于元素,另一个用于List:

class Test> {
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 {
private List data;
public void setData(List t) {data = t;}
public List getData() { return data; }
}