Обобщения, не сохраняемые во время выполнения, конечно, затрудняли понимание концепции на первый взгляд.В любом случае, существуют причины, по которым new ArrayList<String>().getClass()
возвращает Class<?>
, а не Class<String>
, и хотя безопасно привести его к Class<? extends String>
, вы должны помнить, что обобщенные значения существуют только для проверок типов во время компиляции (вроде неявной проверки, есливы будете).
Так что если вы хотите использовать Guice для внедрения MyRepository
(с любым типом) реализации всякий раз, когда вам нужен новый экземпляр Repository
(с любым типом), тогда вам не нужновообще подумайте о дженериках, но вы сами по себе для обеспечения безопасности типов (вот почему вы получаете это надоедливое «непроверенное» предупреждение).
Вот пример кода, который работает просто отлично:
public class GuiceTest extends AbstractModule {
@Inject
List collection;
public static void main(String[] args) {
GuiceTest app = new GuiceTest();
app.test();
}
public void test(){
Injector injector = Guice.createInjector(new GuiceTest());
injector.injectMembers(this);
List<String> strCollection = collection;
strCollection.add("I'm a String");
System.out.println(collection.get(0));
List<Integer> intCollection = collection;
intCollection.add(new Integer(33));
System.out.println(collection.get(1));
}
@Override
protected void configure() {
bind(List.class).to(LinkedList.class);
}
}
Это печатает:
I'm a String
33
Но этот список реализован LinkedList
.Хотя в этом примере, если вы попытаетесь присвоить int что-то, что String , вы получите исключение.
int i = collection.get(0)
Но если вы хотите получитьинъецируемый объект уже приведен к типу, и вы можете запросить List<String>
вместо просто List, но тогда Guice будет рассматривать эту переменную Type как часть ключа привязки (аналогично определителю, например @Named).Это означает, что если вы хотите, чтобы инъекция была конкретно List<String>
для ArrayList<String>
реализации и List<Integer>
для LinkedList<Integer>
, Guice позволяет вам сделать это (не проверено, образованное предположение).
Но есть одна загвоздка:
@Override
protected void configure() {
bind(List<String>.class).to(LinkedList<String>.class); <-- *Not Happening*
}
Как вы могли заметить, литералы класса не являются универсальными .Вот где вы используете TypeLiterals
.
@Override
protected void configure() {
bind(new TypeLiteral<List<String>>(){}).to(new TypeLiteral<LinkedList<String>>(){});
}
TypeLiterals
от Guice, чтобы сохранить переменную универсального типа как часть метаинформации для сопоставления с желаемой реализацией.Надеюсь, это поможет.