假设我有一个像这样的接口:
public interface Converter<T> { /*...*/ }
并假设我在CDI环境中成功完成了此操作:
@Inject
@Any
private Instance<Converter<?>> converters;
(通过“成功”,我的意思是我可以执行以下操作,并在输出中看到几个转换器,因此可以正确地发现并提供bean:
for (final Object o : converters) {
System.out.println("*** converter: " + o);
}
…因此,bean发现不是问题。)
现在假设给定
Integer.class
,我想这样做:final TypeLiteral<Converter<Integer>> typeLiteral = new TypeLiteral<Converter<Integer>>(){};
final Instance<Converter<Integer>> subInstance = converters.select(typeLiteral);
final Converter<Integer> converter = subInstance.get();
这很好。
现在,在我的实际代码中,将
Integer.class
作为满足声明为Class<T>
的参数的值传入,所以我真正拥有的是:final TypeLiteral<Converter<T>> typeLiteral = new TypeLiteral<Converter<T>>(){};
final Instance<Converter<T>> subInstance = converters.select(typeLiteral);
final Converter<T> converter = subInstance.get(); // this does not work
get()
调用失败,并且堆栈跟踪以类似于以下内容的开头:org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type Converter<T> with qualifiers @Any
at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:105)
我该怎么做才能使选择成功?
我注意到的一件事是堆栈报告找不到
Converter<T>
。这看起来很可疑:我希望它用Converter<Integer>
代替,因为在运行时T
的“ slot”是用Integer.class
填充的,尽管,公平地讲,我确实提供了new TypeLiteral<Converter<T>>(){}
,而不是new TypeLiteral<Converter<Integer>>(){}
。无论如何,这一切都告诉我
TypeLiteral<T>
使用T
作为要查找的类型,而不是实际值“填充” T
“插槽”,实际上,没有任何转换器声明为implements Converter<T>
,只有声明为implements Converter<Integer>
的转换器,因此我担心我在这里要做的事情根本上是不可能的。 最佳答案
创建TypeLiteral
以捕获通用参数仅在编译时已知这些参数的情况下有效,因此new TypeLiteral<Converter<Integer>>(){}
。
如果在编译时不知道类型参数,则TypeLiteral无法捕获参数信息,因为该信息已由于类型擦除而被删除。因此,创建new TypeLiteral<Converter<T>>(){}
实际上只是创建一个new TypeLiteral<Converter<object>>(){}
。
这意味着您的select(typeLiteral)
无法正常工作,因为它将收到Converter<object>
的类型文字。
关于java - 我必须使用哪种类型的文字才能使CDI的Instance::select方法正常工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40227804/