简体   繁体   中英

Java Generics - difficulty enforcing strong type checking

Here's my code:

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;
    }
}

This compiles in Eclipse, but on the line within the inner for loop ( row.add(...) ) I get the following three warnings:

  • OrderedPair is a raw type. References to generic type OrderedPair()<T1, T2> should be parameterized.
  • Type Safety: The expression of type OrderedPair needs unchecked conversion to conform to OrderedPair<T, ?>
  • Type safety: The Constructor OrderedPair(Object, Object) belongs to the raw type OrderedPair. References to generic type OrderedPair <T1, T2> should be parameterized

I would like to use generics to enforce strong type-checking here, but I guess my understanding of generics is not sufficient to allow me to see how. Could someone educate me?

Thanks,

-- Ken

The constructor in the inner for loop should have generics:

row.add(new OrderedPair  (sequence.get(rowIndex), secondSequence.sequence.get(columnIndex)));

But you can't use ? like this; so you'll need to replace all the ? s with a letter, say E . Then add an <E> into the signature, like this:

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

Otherwise, the compiler won't know where the E came from.

The OrderedPair is not generified but it's added to a list (Sequence) which is generified. You have to construct the OrderedPair with generics, eg do "new OrderedPair<...>(...)", to get rid of this warning.

Here I have added generics to the whole method, so the return type matches the secondSequence's type:

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));
}

I think that you are a bit confused here. In the type Sequence<T> what will be the T ?

If you define a Sequence<OrderedPair<T, ?>> then you end up with recursion on T.

Please see if what you really need is something like this:

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;
    }
}

Trust compiler and try to use generic parameters always when calling for OrderedPair :) It's not required but I think it's a good practice.

Strict generic applying in Java is not possible because of this:

Type erasure

All you need to do is add a generic type to your constructor, like so:

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

The compiler is throwing errors since OrderedPair expects to receive types <T, ?> while you are passing them without any explicit type. The unchecked conversion the compiler is talking about is since basically you are giving the constructor <?, ?> while it wants <T, ?> hence the unchecked conversion that is going on, and which might throw an exception if the wrong type accidentally gets passed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM