【问题标题】:Java Generics - difficulty enforcing strong type checkingJava 泛型 - 难以执行强类型检查
【发布时间】:2010-09-28 01:49:32
【问题描述】:

这是我的代码:

public class Sequence<T> {

    protected List<T> sequence = new ArrayList<T>();

    public Matrix<OrderedPair<T, ?>> createCartesianProduct(Sequence<?> secondSequence) {
        Matrix<OrderedPair<T, ?>> result = new Matrix<OrderedPair<T, ?>>();
        for (int rowIndex = 0; rowIndex < sequence.size(); rowIndex++) {
            Sequence<OrderedPair<T, ?>> row = new Sequence<OrderedPair<T, ?>>();
            for (int columnIndex = 0; columnIndex < secondSequence.length(); columnIndex++) {
                row.add(new OrderedPair(sequence.get(rowIndex), secondSequence.sequence.get(columnIndex)));
            }
        }
        return result;
    }
}

这在 Eclipse 中编译,但在内部 for 循环 ( row.add(...) ) 内的行上,我收到以下三个警告:

  • OrderedPair 是原始类型。对泛型类型OrderedPair()&lt;T1, T2&gt; 的引用应该被参数化。
  • 类型安全:OrderedPair 类型的表达式需要未经检查的转换才能符合OrderedPair&lt;T, ?&gt;
  • 类型安全:构造函数 OrderedPair(Object, Object) 属于原始类型 OrderedPair。对泛型 OrderedPair&lt;T1, T2&gt; 的引用应该被参数化

我想在这里使用泛型来强制执行强类型检查,但我想我对泛型的理解不足以让我看到如何。有人可以教育我吗?

谢谢,

-- 肯

【问题讨论】:

  • 呃。这就是为什么 refied generics 不应该的原因。 1 在 devoxx。

标签: java generics strong-typing


【解决方案1】:

内部for循环中的构造函数应该有泛型:

row.add(new OrderedPair <T, ?> (sequence.get(rowIndex), secondSequence.sequence.get(columnIndex)));

但是你不能像这样使用?;所以你需要用一个字母替换所有的?s,比如E。然后在签名中添加&lt;E&gt;,如下所示:

public <E> Matrix<OrderedPair<T, E>> createCartesianProduct(Sequence<E> secondSequence) {

否则,编译器将不知道E 来自哪里。

【讨论】:

  • 您肯定需要在此处添加 E,因为您肯定需要强制 secondSequence 中的 E 和 return 中的 E 是同一类型。 ?不起作用,因为 (1) 你不能用 ? 实例化一个对象。类型参数,以及 (2) 不能将任何元素添加到带有 ?类型参数(因此 .add() 会失败),因为您不能保证该元素是“?”的子类型(一些未知类型)。所以肯定需要 E。
【解决方案2】:

OrderedPair 没有被泛化,但它被添加到一个被泛化的列表(序列)中。您必须使用泛型构造 OrderedPair,例如执行“new OrderedPair<...>(...)”,以消除此警告。

这里我为整个方法添加了泛型,所以返回类型与secondSequence的类型匹配:

public <Z> Matrix<OrderedPair<T, Z>> createCartesianProduct(Sequence<Z> secondSequence) {
    Matrix<OrderedPair<T, Z>> result = new Matrix<OrderedPair<T, Z>>();
    for (int rowIndex = 0; rowIndex < sequence.size(); rowIndex++) {
        Sequence<OrderedPair<T, Z>> row = new Sequence<OrderedPair<T, Z>>();
        for (int columnIndex = 0; columnIndex < secondSequence.length(); columnIndex++) {
            addToRow(row, sequence.get(rowIndex), secondSequence.sequence.get(columnIndex));
        }
    }
    return result;
}

static <T, Z> void addToRow(Sequence<OrderedPair<T, Z>> seq, T t, Z z) {
    seq.add(new OrderedPair<T, Z>(t, z));
}

【讨论】:

    【解决方案3】:

    我认为你在这里有点困惑。在Sequence&lt;T&gt; 类型中,T 是什么?

    如果你定义一个Sequence&lt;OrderedPair&lt;T, ?&gt;&gt;,那么你最终会在 T 上递归。

    请看看你真正需要的是不是这样的:

    public class Sequence<T> {
    
        protected List<T> sequence = new ArrayList<T>();
    
        public <T2> Matrix<OrderedPair<T, T2>> createCartesianProduct(Sequence<T2> secondSequence) {
            Matrix<OrderedPair<T, T2>> result = new Matrix<OrderedPair<T, T2>>();
            for (int rowIndex = 0; rowIndex < sequence.size(); rowIndex++) {
                    Sequence<T> row = new Sequence<T>();
                    for (int columnIndex = 0; columnIndex < secondSequence.length(); columnIndex++) {
                            row.add(new OrderedPair<T, T2>(sequence.get(rowIndex), secondSequence.sequence.get(columnIndex)));
                    }
            }
            return result;
        }
    }
    

    【讨论】:

      【解决方案4】:

      信任编译器并尝试在调用 OrderedPair 时始终使用泛型参数 :) 这不是必需的,但我认为这是一个很好的做法。

      因为这个原因,Java 中的严格泛型应用是不可能的:

      Type erasure

      【讨论】:

        【解决方案5】:

        您需要做的就是向您的构造函数添加一个泛型类型,如下所示:

        row.add(new OrderedPair<T, ?>(sequence.get(rowIndex), secondSequence.sequence.get(columnIndex)));
        

        编译器会抛出错误,因为 OrderedPair 期望在您传递它们时接收类型 &lt;T, ?&gt; 而没有任何显式类型。编译器正在谈论的unchecked conversion 是因为基本上你给了构造函数&lt;?, ?&gt; 而它想要&lt;T, ?&gt; 因此正在进行未经检查的转换,如果错误的类型意外通过,可能会引发异常。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-21
          • 1970-01-01
          • 1970-01-01
          • 2016-10-10
          相关资源
          最近更新 更多