views:

873

answers:

5

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

A: 

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

maxnk
A: 

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.

Yuval A
+8  A: 

The constructor in the inner for loop should have generics:

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

If the compiler complains about the "?" (I think it will, but it's not easy for me to test), then replace all the ?'s with a letter, say E. Then add an <E> into the signature, like this:

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

(otherwise, the compiler won't know where the E came from).

Michael Myers
You definitely need to add the E there because you definitely need to enforce that the E in secondSequence and the E in the return are the same type. ? won't work because (1) you cannot instantiate an object with a ? type parameter, and (2) you cannot add any elements to an object with a ? type parameter (so the .add() would fail) because you cannot guarantee that the element is a subtype of "?" (some unknown type). So the E is definitely needed.
newacct
+1  A: 

The OrderedPair is not generified but it's added to a list (Sequence) which is generified. You have to construct the OrderedPair with generics, e.g. 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));
}
volley
+1  A: 

Hi Ken.

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