Java Generics - Difficulty Providing 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 inside the for (row.add (...)) loop, I get the following three warnings:

  • OrderedPair

    is the raw type. Generic type references OrderedPair()<T1, T2>

    must be parameterized.
  • Type Safety: An expression of type OrderedPair requires a raw conversion to match OrderedPair<T, ?>

  • Security type: The constructor OrderedPair (Object, Object) is of the raw OrderedPair type. References to the generic OrderedPair type <T1, T2>

    must be parameterized

I would like to use generics to force type checking here, but I think my understanding of generics is not enough for me to see how to do it. Can anyone enlighten me?

Thank,

- Ken

+1


source to share


5 answers


The constructor in the inner for loop must have generics:

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

      

But you cannot use ?

like this; so you will need to replace everything ?

with a letter for example E

. Then add <E>

to the signature, for example:



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

      

Otherwise, the compiler doesn't know where it came from E

.

+9


source


The OrderedPair is not generated, but is added to the Sequence that is generated. You have to build an OrderedPair with generics for example. do "new OrderedPair <...> (...)" to get rid of this warning.

Here I added generics for the whole method, so the return type matches the type of 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));
}

      

+1


source


I think you are a little confused here. Sequence<T>

Will the type be T

?

If you define a Sequence<OrderedPair<T, ?>>

, then you end up with recursion on T.

See what you really need:

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

      

+1


source


Trace the compiler and try to use shared parameters always when calling OrderedPair :) This is not required , but I think it is good practice.

A strict typical application in Java is not possible because of this:

Erase type

0


source


All you have to do is add a generic type to your constructor, for example:

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

      

The compiler is throwing errors because it OrderedPair

expects to receive types <T, ?>

as long as you pass them without any explicit type. unchecked conversion

the compiler is talking about since basically you are providing a constructor <?, ?>

while it wants <T, ?>

, hence the uncontrolled conversion that happens and that can throw an exception if accidentally mistaken.

0


source







All Articles