Как я использую дженерики с массивом Классов?

Это решение для моего варианта использования основано на ответе Абдельгани.

build.gradle

plugins {
    id 'org.springframework.boot' version '2.1.3.RELEASE'
    id 'java'
}

apply from: 'boot.gradle'

boot.gradle

repositories {
    mavenCentral()
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

dependencies {
    implementation platform('org.springframework.boot:spring-boot-dependencies:2.0.0.RELEASE')

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.0.RELEASE'

    implementation group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: '2.0.0.RELEASE'
}

Короче говоря, сценарий сборки должен иметь 'org. springframework.boot 'доступен как плагин для apply plugin: 'org.springframework.boot' для работы в другом месте.

47
задан skiphoppy 14 April 2009 в 21:25
поделиться

5 ответов

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

Два обходных пути:

  • Придерживайтесь использования коллекции (например, ArrayList > ), который работает так же хорошо, как и массив, и также позволяет расширение.
  • Поместите аннотацию @SuppressWarnings ("unchecked") в код, создающий массив вместе с комментарий, оправдывающий его использование.
23
ответ дан Simon Nickerson 26 November 2019 в 19:52
поделиться

Используйте этот синтаксис:

Class<? extends SuperClass>[] avail = new Class[] { SubClass1.class, ... };

Он выдаст вам предупреждение «не проверено», и это правильно, так как вы можете включать объект Class для типа, который не расширяет SuperClass в массиве.

14
ответ дан erickson 26 November 2019 в 19:52
поделиться

Правильный способ сделать это с массивами - это сделать это с коллекцией. Сожалею! По сложному ряду причин массивы не очень хорошо работают с генериками. Массивы имеют другую модель ковариации, чем обычные объекты, что в конечном итоге вызывает проблемы, с которыми вы сталкиваетесь. Например, с массивами, но не (обычно) с универсальными объектами, вы можете легально сделать это:

Object[] myArray = new String[5];

, а вы не можете сделать это:

LinkedList<Object> myCollection = new LinkedList<String>();

Если вы хотите больше подробностей, вы можете увидеть массивы в обобщениях Java страница из превосходного Generics FAQ

Как сказал simonn, вы также можете просто использовать ваши массивы такими, какие они есть, и использовать @SuppressWarnings ("unchecked") , чтобы заставить замолчать предупреждения. Это будет работать, но без безопасности типов, которую могут предоставить вам дженерики. Если оно'

12
ответ дан Eddie 26 November 2019 в 19:52
поделиться

Но как правильно сделать это с массивами?

Нет безопасного типа для этого; Использование коллекции является правильным подходом. Чтобы понять почему, представьте, если это было разрешено. У вас может быть такая ситуация:

// Illegal!
Object[] baskets = new FruitBasket<? extends Citrus>[10];

// This is okay.
baskets[0] = new FruitBasket<Lemon>();

// Danger! This should fail, but the type system will let it through.
baskets[0] = new FruitBasket<Potato>();

Система типов должна определить, относится ли корзина, добавляемая к массиву, к типу FruitBasket или подтип. FruitBasket не соответствует и должен быть отклонен с ArrayStoreException . Но ничего не происходит!

Из-за стирания типов JVM может видеть только тип времени выполнения массива. Во время выполнения нам нужно сравнить тип массива с типом элемента, чтобы убедиться, что они совпадают. Тип компонента среды выполнения массива - FruitBasket [] после стирания типа; аналогично, элемент " Тип времени выполнения: FruitBasket . Никаких проблем не будет обнаружено - и поэтому это опасно.

5
ответ дан John Feminella 26 November 2019 в 19:52
поделиться

Проблема в том, что создание массива универсального типа недопустимо. Единственный способ обойти это - приведение к универсальному типу при создании массива, но это не очень хорошее решение. (Обратите внимание, что можно использовать универсальный массив, но не создавать его: см. этот вопрос .)

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

2
ответ дан Community 26 November 2019 в 19:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: