Java позволяет вам создавать комбинации интерфейсов, то есть
static class TL<T extends IA & IB> extends TypeLiteral<T>(){}
, но вы заметите, что действительно должен быть конкретный тип T, который реализует оба этих интерфейса.Java не может придумать «комбинированные типы» для переменных - тип должен существовать с реальным файлом класса.
Я с удивлением обнаружил, что это действительно возможно сделать.Я подозреваю, что это темный угол, в который сопровождающие Guice посоветовали бы не входить, и, вероятно, это не очень хорошая идея.
Что следует заметить по поводу кода ниже:
- Яфактически злоупотребляя встроенными мерами безопасности Guice, делая подкласс TL TypeLiteral параметризованным на IA вместо TypeLiteral на T, что было бы правильно.Так что на самом деле весь этот пример, вероятно, работает случайно.
- Это не сильно помогает.Что-то, где-то, наконец, нужно указать конкретный тип (класс Both) в этом случае.Это позволяет вам задавать конкретный тип в классах, которые используют объект, но не тогда, когда вы связываете его или запрашиваете его непосредственно из инжектора
- Почти никто не понимает TypeA &Синтаксис TypeB с обобщениями Java - подготовьтесь к тому, что любой, кто смотрит на этот код, будет полностью сбит с толку, даже некоторые гуру Java
- Если вы позже попытаетесь использовать объект, который реализует только один интерфейсовВы могли бы создать динамический прокси-сервер, который реализует один интерфейс и делегирует объекту, но вам все равно потребуется создать интерфейс, который объединяет эти два параметра, чтобы дать Java тип для ссылки на
публичный класс X {
static final class TL<T extends IA & IB> extends TypeLiteral<IA> {}
interface IA {}
interface IB {}
static final class Both implements IA, IB {}
@Test
public void test() {
Injector inj = Guice.createInjector(new M());
Both object = inj.getInstance(Key.get(new TypeLiteral<Both>(){}));
assertNotNull(object);
Foo<Both> foo = inj.getInstance(Key.get(new TypeLiteral<Foo<Both>>() {}));
assertTrue (object instanceof IA);
assertTrue (object instanceof IB);
assertNotNull(foo);
assertNotNull(foo.obj);
}
static class Foo<T extends IA & IB> {
private final T obj;
@Inject
Foo(T obj) {
this.obj = obj;
}
}
static class M extends AbstractModule {
@Override
protected void configure() {
bind(new TL<Both>()).to(Both.class);
}
}
}
Так что я думаю, что ответ, вы можете, но, вероятно, не должны.