是否可以绑定嵌套泛型?

发布于 2024-08-28 00:21:54 字数 605 浏览 8 评论 0 原文

是否可以将嵌套泛型/捕获绑定在一起?

我经常遇到这样的问题:将类映射到所述类的泛化项。具体来说,我想要这样的东西(不, T 没有在任何地方声明)。

private Map<Class<T>, ServiceLoader<T>> loaders = Maps.newHashMap();

简而言之,我希望 loaders.put/get 具有如下语义:

<T> ServiceLoader<T> get(Class<T> klass) {...}
<T> void put(Class<T> klass, ServiceLoader<T> loader) {...}

以下是我能做的最好的事情吗?我是否必须忍受不可避免的 @SuppressWarnings("unchecked")

private Map<Class<?>, ServiceLoader<?>> loaders = Maps.newHashMap();

Is it possible to tie nested generics/captures together?

I often have the problem of having a Map lookup of class to genericized item of said class. In concrete terms I want something like this (no, T is not declared anywhere).

private Map<Class<T>, ServiceLoader<T>> loaders = Maps.newHashMap();

In short, I want loaders.put/get to have semantics something like these:

<T> ServiceLoader<T> get(Class<T> klass) {...}
<T> void put(Class<T> klass, ServiceLoader<T> loader) {...}

Is the following the best I can do? Do I have to live with the inevitable @SuppressWarnings("unchecked") somewhere down the line?

private Map<Class<?>, ServiceLoader<?>> loaders = Maps.newHashMap();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝眼睛不忧郁 2024-09-04 00:21:54

让我看看如果我明白你的意图:你想要一个存储成对的 Class/ServiceLoader 的映射,其中每对都由相同的 T 参数化,但是 T 之间可能会有所不同?

如果是这种情况,那么最好的解决方案是声明您自己的类,它将展示这样的接口。在内部,它将这些对存储在通用 Map,ServiceLoader> 映射中。

public class MyMap {
   private Map<Class<?>, ServiceLoader<?>> loaders 
      = new HashMaps<Class<?>, ServiceLoader<?>>();

   public<T> void put(Class<T> key, ServiceLoader<T> value) {
      loaders.put(key, value);
   }

   @SuppressWarnings("unchecked")
   public<T> T get(Class<T> key) { return (ServiceLoader<T>) loaders.get(key); }
}

@SuppressWarnings("unchecked") 注释并不是纯粹的邪恶。您应该尽量避免它们,但在某些情况下,您可以发现强制转换是正确的,尽管编译器无法看到这一点。

Let me see If I got your intention: you want a map that stores pairs of Class/ServiceLoader where each pair is parameterized by the same T, but T may be different across pairs?

If this is the case then the best solution is to declare your own class which will exhibit such an interface. Internally it will store these pairs in a generic Map<Class<?>,ServiceLoader<?>> map.

public class MyMap {
   private Map<Class<?>, ServiceLoader<?>> loaders 
      = new HashMaps<Class<?>, ServiceLoader<?>>();

   public<T> void put(Class<T> key, ServiceLoader<T> value) {
      loaders.put(key, value);
   }

   @SuppressWarnings("unchecked")
   public<T> T get(Class<T> key) { return (ServiceLoader<T>) loaders.get(key); }
}

@SuppressWarnings("unchecked") annotations are not pure evil. You should try to avoid them but there are certain cases where you can figure out that the cast is correct despite the fact that the compiler cannot see that.

寄意 2024-09-04 00:21:54

我的建议是为这种情况创建一个新对象。我看到您正在使用 Maps.newHashMap(),所以我认为您使用了 Google Guava,所以我将使用 ForwardingMap

public class Loader<T> extends ForwardingMap<Class<T>, ServiceLoader<T>> {

   private Map<Class<T>, ServiceLoader<T>> delegate = Maps.newHashMap();

}

一个简单的测试证明我的建议是有效的:

public class Loader<T> extends ForwardingMap<Class<T>, Class<T>> {

   private Map<Class<T>, Class<T>> delegate = Maps.newHashMap();

   @Override protected Map<Class<T>, Class<T>> delegate() {
      return delegate;
   }

   public static void main(String[] args) {
      Loader<Integer> l = new Loader<Integer>();

      l.put(Integer.class, Integer.class);

      // error
      l.put(Integer.class, String.class);
   }

}

My suggestion is to create a new Object for such case. I see you were using Maps.newHashMap() so I take it that you used Google Guava so I will use ForwardingMap.

public class Loader<T> extends ForwardingMap<Class<T>, ServiceLoader<T>> {

   private Map<Class<T>, ServiceLoader<T>> delegate = Maps.newHashMap();

}

A simple test proved that my suggestion is working:

public class Loader<T> extends ForwardingMap<Class<T>, Class<T>> {

   private Map<Class<T>, Class<T>> delegate = Maps.newHashMap();

   @Override protected Map<Class<T>, Class<T>> delegate() {
      return delegate;
   }

   public static void main(String[] args) {
      Loader<Integer> l = new Loader<Integer>();

      l.put(Integer.class, Integer.class);

      // error
      l.put(Integer.class, String.class);
   }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文