Java Generics - 难以强制执行强类型检查

时间:2008-12-22 19:22:18

标签: java generics strong-typing

这是我的代码:

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()<T1, T2>
  • 类型安全:OrderedPair类型的表达式需要未经检查的转换以符合OrderedPair<T, ?>
  • 类型安全:构造函数OrderedPair(Object,Object)属于原始类型OrderedPair。对泛型类型OrderedPair <T1, T2>的引用应该参数化

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

谢谢,

- 肯

5 个答案:

答案 0 :(得分:9)

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

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

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

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

否则,编译器将不知道E来自何处。

答案 1 :(得分:1)

OrderedPair没有被广泛化,但它被添加到一个列表(序列)中,这个列表是通用的。您必须使用泛型构造OrderedPair,例如做“新的OrderedPair&lt; ...&gt;(...)”,以摆脱这个警告。

这里我已经为整个方法添加了泛型,因此返回类型与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));
}

答案 2 :(得分:1)

我认为你在这里有点困惑。在Sequence<T>类型中,T是什么?

如果定义Sequence<OrderedPair<T, ?>>,那么最终会在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;
    }
}

答案 3 :(得分:0)

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

因此无法在Java中严格通用:

Type erasure

答案 4 :(得分:0)

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

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

编译器抛出错误,因为OrderedPair期望在传递类型<T, ?>时没有任何显式类型。编译器正在讨论的unchecked conversion是因为基本上你正在给构造函数<?, ?>,因为它需要<T, ?>因此未经检查的转换正在进行,并且如果错误则可能抛出异常意外地通过了类型。