【问题标题】:How to implement a ServiceLocator with generics?如何使用泛型实现 ServiceLocator?
【发布时间】:2016-06-13 14:12:03
【问题描述】:

有这个接口:

public interface ServiceLocator {
    <T> void setService(Class<T> klass, Factory<T> factory)

    <T> void setConstant(Class<T> klass, T value)

    <T> T getObject(Class<T> klass)

}

如何实现它?我的意思是,我如何声明结构数据? 是这样吗?

private Map<Class, Factory> services = new HashMap<>();
private Map<Class, Object> constants = new HashMap<>();

【问题讨论】:

  • 就是这样,您仍然可以添加通配符来摆脱原始类型的警告。 Map&lt;Class&lt;?&gt;, Factory&lt;?&gt;&gt;.
  • 但是使用泛型来拥有安全类型难道不是重点吗?我指的是具有 Object 类型的 constantsdeclaration。有了这个,当我对一个常量执行getObject 时,我不得不进行强制转换:(T) constants.get(klass); 这不对,不是吗?
  • 您无法通过类型系统获得那种级别的安全性。但是你已经(大部分)以封装的形式拥有它。
  • 没有安全的方法让 Map 为每个键返回不同的泛型类型。
  • Java 类型系统不足以证明您所做的是类型安全的。您可以自己证明这一点,并使用不安全的强制类型转换将其隐藏在类型系统中,但这是您能做的最好的事情。

标签: java generics hashmap


【解决方案1】:
private Map<Class, Factory> services = new HashMap<>();
private Map<Class, Object> constants = new HashMap<>();

如果你想使用这个结构,你可以这样声明:

private Map<Class<?>, Factory<T>> services = new HashMap<>();
private Map<Class<?>, Object> constants = new HashMap<>();

记得输入Factory&lt;T&gt; 来捕捉类型。 Using Class 让您可以使用 AnyClass.class 作为 Key

顺便说一句,您可以将所有内容放在一个 Map 中,例如 private Map&lt;Class&lt;?&gt;, Object&gt;,然后在 get 函数中将其转换为工厂与否;)

【讨论】:

  • Map&lt;Class&lt;?&gt;, Factory&lt;T&gt;&gt; services 不可能,因为我不希望实现是通用的,只有方法。将所有内容放在一张地图中是一种选择,但我更喜欢其他方式,它相同但更干净,不是吗?
  • 好吧,如果是这样的话,两张地图会更干净;)
【解决方案2】:

解决方案:

private Map<Class<?>, Factory<?>> services = new HashMap<>();
private Map<Class<?>, Object> constants = new HashMap<>();

-Xlint:unchecked 指令添加到编译器选项。 和@SuppressWarnings("unchecked") 在您需要的方法上。在我的情况下是 getObject 方法。

【讨论】:

    【解决方案3】:

    Guava 有一个用于类似目的的接口:ClassToInstanceMap&lt;B&gt;。 API 是:

    <T extends B> T getInstance(Class<T> type);
    <T extends B> T putInstance(Class<T> type, T value);
    

    查看MutableClassToInstanceMap.java 中的实现,我们看到它使用HashMap&lt;Class&lt;? extends B&gt;, B&gt; 包裹在ConstrainedMap 中。它的MapConstraint 使用java.lang.Class.cast() 来确保映射中的所有值都是其对应键的合法实例。

    由于B 通常只是Object,因此实现的HashMap 最终只是HashMap&lt;Class&lt;? extends Object&gt;, Object&gt;

    【讨论】:

      猜你喜欢
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 2023-03-03
      • 1970-01-01
      相关资源
      最近更新 更多