Внедрение дженериков с помощью Guice - PullRequest
28 голосов
/ 06 апреля 2010

Я пытаюсь перенести небольшой проект, заменив некоторые фабрики на Guice (это мое первое испытание на Guice). Тем не менее, я застрял при попытке ввести дженерики. Мне удалось извлечь небольшой игрушечный пример с двумя классами и модулем:

import com.google.inject.Inject;

public class Console<T> {
  private final StringOutput<T> out;
  @Inject
  public Console(StringOutput<T> out) {
    this.out = out;
  }
  public void print(T t) {
    System.out.println(out.converter(t));
  }
}

public class StringOutput<T> {
  public String converter(T t) {
    return t.toString();
  }
}

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;


public class MyModule extends AbstractModule {

  @Override
  protected void configure() {
    bind(StringOutput.class);
    bind(Console.class);
  }

  public static void main(String[] args) {
    Injector injector = Guice.createInjector( new MyModule() );
    StringOutput<Integer> out = injector.getInstance(StringOutput.class);
    System.out.println( out.converter(12) );
    Console<Double> cons = injector.getInstance(Console.class);
    cons.print(123.0);
  }

}

Когда я запускаю этот пример, все, что я получаю, это:

Исключение в ветке "main" com.google.inject.CreationException: ошибки создания Guice:

1) playground.StringOutput<T> cannot be used as a key; It is not fully specified.
  at playground.MyModule.configure(MyModule.java:15)

1 error
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354)
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152)
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105)
    at com.google.inject.Guice.createInjector(Guice.java:92)

Я пытался найти сообщение об ошибке, но не нашел никаких полезных советов. Далее в FAQ Guice я наткнулся на вопрос о том, как вводить дженерики. Я пытался добавить следующую привязку в методе configure:

bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>());

Но без успеха (то же сообщение об ошибке).

Может кто-нибудь объяснить мне сообщение об ошибке и дать мне несколько советов? Спасибо.

1 Ответ

28 голосов
/ 06 апреля 2010

Я думаю, что конкретная проблема, которую вы видите, возможно, связана с утверждением bind(Console.class). Также следует использовать TypeLiteral. Или вы можете просто не связывать ни одно из них, и JIT-связывание позаботится об этом за вас, так как оба типа, используемые здесь, являются конкретными классами.

Кроме того, вы должны получить Console с:

Console<Double> cons = 
   injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){}));

Редактировать: Вам не нужно привязываться к экземпляру только потому, что вы используете TypeLiteral. Вы можете просто сделать:

bind(new TypeLiteral<Console<Double>>(){});

Конечно, как я уже говорил выше, вы можете просто пропустить это в этом случае и извлечь Console из инжектора, используя Key на основе TypeLiteral, и привязка будет неявной.

...