ParameterizedType
- это класс java, который используется для представления типов, которые в исходном коде java необходимо писать в угловых скобках: такие типы, как Foo<Bar>
или Set<Option>
или Set<Option<Radio>>
или даже Set<? extends Option<Radio>>
. Это возвращаемое значение, которое вы хотите.
То, что вы сделали, на самом деле будет корректно работать с очень незначительным изменением, которое вы хотите назвать superClass.getType()
в строке, следующей за последней, вместо superClass.getRawType()
. При этом, пока я здесь, у меня есть несколько других предложений.
Прежде всего, в вашем первом методе я бы изменил его на:
<T> Key<Set<T>> bindMultibinder(
Iterable<? extends Class<? extends T>> contents, Class<T> superClass) {
Named annotation = randomAnnotation();
Multibinder<T> options =
Multibinder.newSetBinder(binder(), superClass, annotation);
for (Class<? extends T> t : contents) {
options.addBinding().to(t);
}
@SuppressWarnings("unchecked")
final Key<Set<T>> multibinderKey = (Key<Set<T>>) Key.get(Types.setOf( superClass ), annotation);
return multibinderKey;
}
Это позволит вам делать звонки так:
bindMultibinder(ImmutableList.of(CruiseControlSubOptOne.class,
CruiseControlSubOptTwo.class),
Option.class);
Или, если вы не используете гуава - хотя вы должны это сделать - вы можете использовать Arrays.asList
вместо ImmutableList.of
. Вы получаете такой же уровень безопасности типов, как и раньше, без необходимости указывать все эти угловые скобки в вашем коде привязки.
Если у вас пока нет большого числа вызывающих bindMultibinder
, я бы также поменял порядок аргументов, но это может быть просто личный стиль.
С этими же изменениями ваш второй метод становится:
<T> Key<Set<T>> bindMultibinder(
Iterable<? extends TypeLiteral<? extends T>> contents, TypeLiteral<T> superClass) {
Named annotation = randomAnnotation();
Multibinder<T> options =
Multibinder.newSetBinder(binder(), superClass, annotation);
for (TypeLiteral<? extends T> t : contents) {
options.addBinding().to(t);
}
@SuppressWarnings("unchecked")
final Key<Set<T>> multibinderKey = (Key<Set<T>>) Key.get(Types.setOf(superClass.getType()), annotation);
return multibinderKey;
}
И вы можете использовать его аналогично:
bindMultibinder(ImmutableList.of(
new TypeLiteral<CruiseControlSubOptOne>() {},
new TypeLiteral<CruiseControlSubOptTwo>() {}),
new TypeLiteral<Option>() {});
Подумав об этом сейчас, мне интересно, действительно ли вы хотите перегрузку bindMultibinder
, которая занимает TypeLiteral
. Разве вы не предпочли бы один, который вместо Key
?
<T> Key<Set<T>> bindMultibinder(Iterable<? extends Key<? extends T>> contents, Key<T> superClass) {
Named annotation = randomAnnotation();
Multibinder<T> options =
Multibinder.newSetBinder(binder(), superClass.getTypeLiteral(), annotation);
for (Key<? extends T> t : contents) {
options.addBinding().to(t);
}
@SuppressWarnings("unchecked")
final Key<Set<T>> multibinderKey =
(Key<Set<T>>) Key.get(Types.setOf(superClass.getTypeLiteral().getType()), annotation);
return multibinderKey;
}
В конце концов, вы можете вызывать этот метод почти таким же образом:
bindMultibinder(ImmutableList.of(
new Key<CruiseControlSubOptOne>() {},
new Key<CruiseControlSubOptTwo>() {}),
new Key<Option>() {});
За исключением того, что Key
легче набрать, чем TypeLiteral
, и если вам нужно вставить что-то, что идентифицируется только его аннотацией, это тривиально:
bindMultibinder(ImmutableList.of(
new Key<CruiseControlSubOptOne>() {},
new Key<CruiseControlSubOptTwo>() {},
Key.get(CruiseControl.class, Names.named("ThirdOpt")),
Key.get(CruiseControl.class, Names.named("FourthOpt"))),
new Key<Option>() {});
Теперь, это @Suppress
заставляет вас нервничать? Хорошие инстинкты.
К сожалению, печальный факт заключается в том, что при работе с отражением вокруг обобщенных типов - типов с угловыми скобками в них - вы почти наверняка получите маленькие непроверенные биты. Мое предложение заключается в том, что вы должны сделать так, чтобы нетипизированные предупреждения подавлялись как можно меньше, и выставлять внешнему миру как можно больше информации о типах. Если вы вернете Key<?>
отсюда, вы, вероятно, заставите вызывающего этого метода подавлять нетипизированные предупреждения, когда они пытаются использовать ваше возвращаемое значение. Лучше сделать это здесь, где вы можете ограничить подавление предупреждений одной строкой, а другой - доказать, что приведение является безопасным.