Java Generics - сложность принудительной строгой проверки типов - PullRequest
1 голос
/ 22 декабря 2008

Вот мой код:

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 ]

9 голосов
/ 22 декабря 2008

Конструктор во внутреннем цикле for должен иметь обобщенные значения:

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

Но вы не можете использовать ? вот так; поэтому вам нужно заменить все ? на буквы, скажем E. Затем добавьте <E> в подпись, например:

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

В противном случае компилятор не будет знать, откуда взялся E.

1 голос
/ 22 декабря 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;
    }
}
1 голос
/ 22 декабря 2008

OrderedPair не генерируется, но добавляется в список (последовательность), который генерируется. Вы должны построить 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));
}
0 голосов
/ 22 декабря 2008

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

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

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

0 голосов
/ 22 декабря 2008

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

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

Тип стирания

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...