简体   繁体   English

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

[英]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涉及TList<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例如通过声明TList<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.

相关问题 Java通用类绑定到类型扩展T <E> - Java Generic class bound to type extending T<E> 怎么做 <T extends E> 泛型类型参数包容性? - How to make <T extends E> generic type argument inclusive? 泛型 <T extends List<E> &gt;适用于:每个打印 - Generic <T extends List<E>> for:each print 类型参数为E的子类的泛型E - Generic class E with type parameter to be a subclass of E 是否有可能检索用于类型标记的通用类型(即Class <T> )在运行时? - Is it possible to retrieve the generic type used for a type token (i.e. Class<T>) at runtime? 用于泛型类型的Java转换“.class”-operator,例如列表,到“Class <List <?>>”和“Class <List <Integer >>” - Java casting “.class”-operator used on a generic type, e.g. List, to “Class<List<?>>” and to “Class<List<Integer>>” 最简单的方法来转换类 <T> 到一个班级 <E extends Enum<E> &gt;不丢失类型信息 - Simplest way to cast a Class<T> to a Class<E extends Enum<E>> without losing type information 清单 <E> 不喜欢我的自定义课程 - List<E> doesn't like my custom class 如何使用扩展类 <E extends Comparable<E> &gt; - How to extend Generic abstract Class with <E extends Comparable<E>> 如何用E ...元素编写Java泛型方法并返回List <E> - How to write Java generic method with E… elements and return List<E>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM