Это решение для моего варианта использования основано на ответе Абдельгани.
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'
для работы в другом месте.
Это кажется немного пораженческим, но именно такие проблемы и являются причиной того, что большинство людей избегают смешивать массивы и дженерики. Из-за способа реализации обобщений (стирание типа ) массивы и обобщения никогда не будут работать вместе.
Два обходных пути:
ArrayList >
), который работает так же хорошо, как и массив, и также позволяет расширение. @SuppressWarnings ("unchecked")
в код, создающий массив вместе с комментарий, оправдывающий его использование. Используйте этот синтаксис:
Class<? extends SuperClass>[] avail = new Class[] { SubClass1.class, ... };
Он выдаст вам предупреждение «не проверено», и это правильно, так как вы можете включать объект Class
для типа, который не расширяет SuperClass
в массиве.
Правильный способ сделать это с массивами - это сделать это с коллекцией. Сожалею! По сложному ряду причин массивы не очень хорошо работают с генериками. Массивы имеют другую модель ковариации, чем обычные объекты, что в конечном итоге вызывает проблемы, с которыми вы сталкиваетесь. Например, с массивами, но не (обычно) с универсальными объектами, вы можете легально сделать это:
Object[] myArray = new String[5];
, а вы не можете сделать это:
LinkedList<Object> myCollection = new LinkedList<String>();
Если вы хотите больше подробностей, вы можете увидеть массивы в обобщениях Java страница из превосходного Generics FAQ
Как сказал simonn, вы также можете просто использовать ваши массивы такими, какие они есть, и использовать @SuppressWarnings ("unchecked")
, чтобы заставить замолчать предупреждения. Это будет работать, но без безопасности типов, которую могут предоставить вам дженерики. Если оно'
Но как правильно сделать это с массивами?
Нет безопасного типа для этого; Использование коллекции является правильным подходом. Чтобы понять почему, представьте, если это было разрешено. У вас может быть такая ситуация:
// 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
. Никаких проблем не будет обнаружено - и поэтому это опасно.
Проблема в том, что создание массива универсального типа недопустимо. Единственный способ обойти это - приведение к универсальному типу при создании массива, но это не очень хорошее решение. (Обратите внимание, что можно использовать универсальный массив, но не создавать его: см. этот вопрос .)
В любом случае вы почти всегда должны использовать списки вместо массивов, поэтому Я думаю, что вы уже нашли лучшее решение.