使用 Guice 注入泛型

2022-09-01 13:20:05

我正在尝试迁移一个小项目,用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)

我尝试查找错误消息,但没有找到任何有用的提示。在Guice FAQ的进一步中,我偶然发现了一个关于如何注入泛型的问题。我试图在方法中添加以下绑定:configure

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

但没有成功(相同的错误消息)。

有人可以向我解释错误消息并向我提供一些提示吗?谢谢。


答案 1

我认为你看到的具体问题可能是因为这个声明。它还应该使用 a。或者,您可以只绑定其中任何一个,JIT绑定将为您处理它,因为这里涉及的两种类型都是具体的类。bind(Console.class)TypeLiteral

此外,您还应该检索 with:Console

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

编辑:您不需要仅仅因为使用了 .你可以做:TypeLiteral

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

当然,就像我上面说的,在这种情况下,你可以跳过它,并使用基于 和 绑定从注入器中检索。ConsoleKeyTypeLiteral


答案 2

推荐