Java Generics - трудности с обеспечением строгой проверки типов

Вот мой код:

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> должны быть параметризованы.

Я хотел бы использовать здесь универсальные шаблоны для обеспечения строгой проверки типов, но полагаю, что моего понимания универсальных шаблонов недостаточно, чтобы понять, как это сделать. Может ли кто-нибудь научить меня?

Спасибо,

- Кен


person Community    schedule 22.12.2008    source источник
comment
фу. Вот почему refied дженериков не должно было быть. 1 в DevOxx.   -  person Ran Biron    schedule 22.12.2008


Ответы (5)


Конструктор во внутреннем цикле 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.

person Michael Myers    schedule 22.12.2008
comment
Вам определенно нужно добавить E туда, потому что вам определенно нужно обеспечить, чтобы E в secondSequence и E в возвращении были одного и того же типа. ? не будет работать, потому что (1) вы не можете создать экземпляр объекта с помощью? параметр типа, и (2) вы не можете добавлять какие-либо элементы к объекту с? параметр типа (так что .add () не сработает), потому что вы не можете гарантировать, что элемент является подтипом? (какой-то неизвестный тип). Так что буква Е определенно нужна. - person newacct; 02.05.2009

OrderedPair не генерируется, но добавляется в список (Sequence), который генерируется. Вы должны создать 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));
}
person volley    schedule 22.12.2008

Я думаю, что вы здесь немного запутались. В типе 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;
    }
}
person bruno conde    schedule 22.12.2008

Доверяйте компилятору и старайтесь всегда использовать общие параметры при вызове OrderedPair :) Это не требуется, но я думаю, что это хорошая практика.

Строгое универсальное применение в Java невозможно из-за этого:

Удаление типа

person maxnk    schedule 22.12.2008

Все, что вам нужно сделать, это добавить в конструктор универсальный тип, например:

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

Компилятор выдает ошибки, поскольку OrderedPair ожидает получения типов <T, ?>, пока вы их передаете без явного типа. unchecked conversion, о котором говорит компилятор, заключается в том, что в основном вы даете конструктору <?, ?>, а он хочет <T, ?>, следовательно, происходит неконтролируемое преобразование, которое может вызвать исключение, если случайно будет передан неправильный тип.

person Yuval Adam    schedule 22.12.2008