Можно ли использовать дженерики в списках в Java 1.4?

StackOverflow https://stackoverflow.com/questions/6320313

  •  27-10-2019
  •  | 
  •  

Вопрос

Я должен использовать Java 1.4 и использую структуры arraylist.Теперь мне нужно провести некоторый рефакторинг, и это помогло бы, если бы я мог использовать дженерики.В настоящее время у меня есть такой код, как этот

ArrayList rows = new ArrayList();

Который представляет собой простой ArrayList.Но теперь переменная "rows" становится все более сложной, и необходимо определить класс "Row".Теперь я хочу сделать что-то вроде того, что вы видите в J2SE 1.5

ArrayList<Row> rows = new ArrayList();

Поиск через Google не дает никаких ответов без некоторого сложного использования сторонних решений.Как должен был бы измениться мой код, чтобы учесть это в версии 1.4, без использования сторонних решений / проектов с открытым исходным кодом (если возможно)?

Это было полезно?

Решение

Дженерики были введены в JDK 1.5.Таким образом, вы не можете использовать их в версии 1.4.Тем не менее, вы можете использовать компилятор JDK 1.5, но ориентироваться на 1.4 со своими классами с -target 1.4 опция javac при сохранении -source 1.5 возможность указать, что ваш исходный код совместим с версией 1.5.В этом случае вы можете использовать дженерики, поскольку они не должны влиять на результирующие классы.

Смотрите раздел, посвященный параметрам кросс-компиляции

Другие советы

Generics, как правило, решает проблему того, что я считаю "наивными приведениями" в Java 1.4 или более ранних версиях при работе с коллекциями.В Java 1.5+ строка, которую вы разместили:

ArrayList<Row> rows = new ArrayList();

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

ArrayList<Row> rows = new ArrayList<Row>();

Это сообщает компилятору, что ваш объект ArrayList всегда должен содержать только тип строки.

Однако, поскольку Java 1.5 обратно совместима с огромными наборами библиотек, которые содержат не этот синтаксис, а скорее ваш предыдущий код:

ArrayList rows = new ArrayList();

Дженерики, очевидно, не будут работать с этими старыми библиотеками - поэтому дженерики являются всего лишь время компиляции вариант - классы 1.5 и 1.4 фактически эквивалентны (за вычетом любого внутреннего рефакторинга / новых методов, добавленных позже), потому что они действительно являются реализациями ArrayList, которые обрабатывают любой тип объекта.

Код 1.5 просто добавляет прямое приведение для вас.

В коде 1.4 допустим, вы хотели выполнить итерацию по ArrayList.Наивный способ сделать это следующим образом:

for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
    Row row = (Row) rowIterator.next();
    // Do something with the row.
}

Код Java 1.5 в точности эквивалентен версии naive cast.Для этого требуется тот факт, что вы сообщаете компилятору, что это является строку и выполняет этот код за вас.Таким образом, преимущества синтаксического сахара приятнее (при этом используется более новый синтаксис для каждого цикла, но генерируется тот же код, что и в приведенном выше цикле).:

for(Row row : rows) {
   // Do something with the row
}

Итак, если вы хотите использовать ArrayList, содержащий только строки, вы все равно можете это сделать.Но нет никакого способа заставить компилятор проверить что ArrayList содержит только все строки (хотя, даже несмотря на то, что компилятор предоставляет эту проверку, это все еще возможно для отправки ArrayList, который содержит объекты других типов, поскольку, опять же, ArrayList по-прежнему действительно обрабатывает только тип объекта, а обобщения удаляются во время выполнения - все, что остается, это наивный приведенный код, который вы больше не видите).

Не наивный вариант состоит в том, чтобы проверять каждый экземпляр и самостоятельно создавать ClassCastException с информативным сообщением (вместо того, чтобы программа выбрасывала его с сообщением по умолчанию):

for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
    Object shouldBeRow = rowIterator.next();
    if(!(shouldBeRow instanceof Row)) {
        throw new ClassCastException("The object " + shouldBeRow + " is not an instance of Row - only Rows should be present in the list!");
    }
    Row row = (Row) shouldBeRow;
    // Do something with the row.
}

Однако, как правило, никто этого не делает - хорошая документация может сделать эту проблему спорной, поскольку она возлагает бремя предоставления правильной коллекции на вызывающую программу, и, таким образом, вы можете просто вызвать исключение ClassCastException, генерируемое JVM.

Да, ты можешь.Используйте компилятор 1.5 и используйте

javac -target jsr14 ............

Это сгенерирует классы java 1.4, но позволит использовать дженерики.

Этот переключатель может использоваться только для функций, не отображаемых в байтовом коде 1.5.Например, вы не можете использовать перечисления или новые методы, представленные в 1.5.Но дженерики - это нормально, поскольку на самом деле они не присутствуют в байт-коде.

Нет, вы не можете использовать их в JDK 1.4.Они были представлены в JDK1.5

Все, что вам нужно сделать, это разыграть их.Это может привести к исключению во время выполнения, если вы добавите в список "неправильные" типы.

Row arow = (Row) rows.get(0);

for ($i=0; i<rows.size(); $i++){
    Row element = (Row) rows.get($i);
    element.printCells();
    (...)
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top