简体   繁体   English

获取类定义中泛型的参数化类型

[英]Get the parameterized type of a generic in class definition

I am writing a class that takes in a parameterized type, which I am trying to parameterize. 我正在编写一个接受参数化类型的类,我正在尝试对其进行参数化。

So I have a User object which has an ID. 所以我有一个具有ID的User对象。 I am making ID a parameterized type. 我正在将ID设置为参数化类型。 I have a class called Router that needs to provide one method T route(List<T>); 我有一个称为Router的类,需要提供一个方法T route(List<T>); , where T extends User . ,其中T extends User

Within Router I have some utility methods where I need to group by an ID within User, which is also parameterized. Router我有一些实用方法,需要在User中按ID进行分组,该ID也已参数化。 So User looks like User<K> , where K is the type of ID. 所以User看起来像User<K> ,其中K是ID的类型。 So I would have a method that looks like the following within Router: 因此,我将在Router中使用类似于以下方法的方法:

public T route(List<T> listToRoute) {
  Map<K, Double> someUtilityMap = groupValueById(listToRoute);
  // apply some logic
  return chooseFinalCandidate(someUtilityMap);
}

Currently I have: 目前我有:

public class Router<K, T extends User<K>> {

Is there a cleaner way to get and reference K within Router without the callers having to provide it explicitly in instantiation? 有没有一种更干净的方法来获取和引用Router内的K ,而调用者不必在实例化中显式提供它? Can I somehow just give T and then use K in the Router implementation? 我可以在Router实现中以某种方式给T然后使用K吗?

I need to reference K explicitly in code, so something like: 我需要在代码中显式引用K ,所以类似:

Map<K, Double> groupValueById(List<T> routingCandidates) {

What I would like to do is something like: 我想做的是这样的:

new Router<User<Integer>>();

as opposed to: 相对于:

new Router<Integer, User<Integer>>();

I would suggest you to change the signature or your class to public class Router2<K> . 我建议您将签名或您的类更改为public class Router2<K>

Currently, I understand, you have something like 目前,据我了解,您有类似

public class Router<K, T extends User<K>> {
  Map<K, Double> groupValueById(List<T> routingCandidates) {
    return null;
  }
}

Then call it like 然后像这样称呼它

List<User<Integer>> list = new ArrayList<>();
Router<Integer, User<Integer>> router = new Router<>();
Map<Integer, Double> map = router.groupValueById(list);

You can change it to something like 您可以将其更改为

public class Router<K> {
  <T extends User<K>> Map<K, Double> groupValueById(List<T> routingCandidates) {
    return null;
  }
}

and call it like 并称它为

List<User<Integer>> list = new ArrayList<>();
Router<Integer> router = new Router<>();
Map<Integer, Double> map = router.groupValueById(list);

Although it might seem that we only move the problem to another place, it makes it much simpler to use the class, because you do not need to write down the generic type parameters when using the method. 尽管似乎我们只将问题移到了另一个地方,但是它使使用该类更加容易,因为使用该方法时无需写下泛型类型参数。

I think there are two concepts here, that have to be kept separated: 我认为这里有两个概念,必须分开:

  1. The type parameter of the class 类的类型参数
  2. The type that the class operates on 类操作的类型

The only varibale type that is not known in advance and that has to be filled in is K . 事先不知道并且必须填写的唯一变量类型是K When you know K , you can derive User<K> from it. 当知道K ,可以从中导出User<K> User is always the same. User始终相同。 So this class should have only one type parameter: K . 因此,此类仅应具有一个类型参数: K This is sufficient for defining the concrete classes. 这足以定义具体的类。

The class operates on objects of type User<K> . 该类对User<K>类型的对象进行User<K> You try to express this by type parameters, but this is not what generics are made for. 您尝试通过类型参数来表达它,但这不是泛型的目的。 I do not know of a way to capture the K from User<K> and I think it is not necessary here. 我不知道从User<K>捕获K的方法,我认为这里没有必要。 It would only make the definition more complicated than necessary. 这只会使定义变得比必要的更为复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM