【问题标题】:Cast from ? to T in Java从 ?到 Java 中的 T
【发布时间】:2014-05-25 08:01:52
【问题描述】:

我正在尝试使用泛型来保持良好的抽象。

在几个班级之间移动“未经检查的演员”之后,我不得不选择哪个“未经检查的演员”是较小的邪恶,这就是我得到的:

public class DaoFactory {
    private static DaoFactory instance;
    private HashMap<String, Dao<?, BigDecimal>> registeredClasses = new HashMap<String, Dao<?, BigDecimal>>();

    private DaoFactory() {
    }

    public static synchronized DaoFactory getInstance() {
        if (instance == null)
            instance = new DaoFactory();

        return instance;
    }

    public <T> void registerDao(String daoId, Dao<T, BigDecimal> d) {
        registeredClasses.put(daoId, d);
    }

    @SuppressWarnings("unchecked")
    public <T> Dao<T, BigDecimal> createDao(String daoId) {
        return (Dao<T, BigDecimal>) (registeredClasses.get(daoId)).createDao();
    }
}

如您所见,我添加了一个@SuppressWarnings("unchecked"),我在其中收到“未经检查的演员表”警告。

这就是问题所在:registeredClasses 不能HashMap&lt;String, Dao&lt;T, BigDecimal&gt;&gt;,因为我需要将类型参数 T 添加到 DaoFactory 类(它将是 class DaoFactory&lt;T&gt; )。如果我添加该参数,那么instance = new DaoFactory(); 也需要&lt;T&gt;。但它在一个静态数学中(DaoFactory 是一个单例),所以我不能使用T。所以我使用HashMap&lt;String, Dao&lt;?, BigDecimal&gt;&gt; registeredClasses 而不是HashMap&lt;String, Dao&lt;T, BigDecimal&gt;&gt; registeredClasses

所以我在这个工厂类中有“&lt;T&gt;-world”和“&lt;?&gt;-world”。所以我必须从Dao&lt;?, BigDecimal&gt; 转换为Dao&lt;T, BigDecimal&gt; 并使用@SuppressWarnings("unchecked")。你觉得这可以接受吗?

【问题讨论】:

  • 嗯,解决方案基本上是类型不安全的,因为registeredClasses 是一个非同质映射,包含各种类型的 Dao。那肯定会在某处冒泡。
  • 这很奇怪,但是,您在 Dao 的实例上调用 createDao() 以获得相同类型的 Dao
  • 有些类是extends Dao(例如:Impl1Dao),它们有它们的createDao() return new Impl1Dao();
  • 那么Dao既是DAO又是DAO工厂?这是一种奇怪的做法。
  • 正如我所说,我会使用配套工厂类。它可以是 DAO 类中的一个小型静态类。但是,如果您没有从中获得任何收益,请坚持现有的。无论如何,所有这些都与您关于类型不安全的问题无关。

标签: java casting


【解决方案1】:

我不确定这在多大程度上是可行的,因为您需要一个 Class 对象来转换;因为类型擦除将 T 变成了 Object。

public void registerDao(String daoId, Dao<Object, BigDecimal> d) {
    registeredClasses.put(daoId, d);
}

public <T> Dao<T, BigDecimal> createDao(Class<Dao<T, BigDecimal>> klazz,
                                        String daoId) {
    return klazz.cast(registeredClasses.get(daoId).createDao());
}

Dao 总结在这里没有帮助,最好使用Class&lt;T&gt;

【讨论】:

  • createDaoDao 的实例方法,它完全了解它的类。你只需要dao.getClass().cast(...) 但是,整个演员阵容没有任何收获,因为呼叫站点已经存在相同的演员。
  • @MarkoTopolnik 是的,但问题是返回 TDao&lt;&gt; - 如果没有至少一个 class&lt;T&gt;,这是无法安全完成的。我怀疑&lt;T&gt; T getT(Class&lt;T&gt; klazz) 可能更有意义。
  • 这只是关于类型推断,在某些情况下可以在没有类型标签的情况下工作(而在其他情况下则不会)。所以这与类型安全无关。
  • 也许它没有太大的区别,但是 Joop 发布的代码并没有给出警告。附言但它在其他类中给出了错误:-D 在某个地方我需要一个给出警告的演员。
猜你喜欢
  • 2013-08-16
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多