Java 泛型地狱:我可以构造一个TypeLiteral<;设置<;T>&燃气轮机;使用泛型?
我能够让下面的通用方法工作的唯一方法是传递看似冗余的Java 泛型地狱:我可以构造一个TypeLiteral<;设置<;T>&燃气轮机;使用泛型?,java,generics,types,set,guice,Java,Generics,Types,Set,Guice,我能够让下面的通用方法工作的唯一方法是传递看似冗余的TypeLiteral参数。我相信在给定另一个参数的情况下,应该可以通过编程的方式构造这个参数,但是我不知道如何构造 protected <T> Key<Set<T>> bindMultibinder( TypeLiteral<Set<T>> superClassSet, TypeLiteral<T> superClass) { final Key<Set&l
TypeLiteral
参数。我相信在给定另一个参数的情况下,应该可以通过编程的方式构造这个参数,但是我不知道如何构造
protected <T> Key<Set<T>> bindMultibinder(
TypeLiteral<Set<T>> superClassSet, TypeLiteral<T> superClass) {
final Key<Set<T>> multibinderKey = Key.get(superClassSet, randomAnnotation);
return multibinderKey;
}
受保护密钥绑定多绑定器(
TypeLiteral超类集,TypeLiteral超类){
final Key multibinderKey=Key.get(超类集,随机注释);
返回multibinderKey;
}
客户端代码如下所示:
bindMultibinder(new TypeLiteral<Set<A<B>>>(){}, new TypeLiteral<A<B>>(){});
bindMultibinder(newTypeLiteral(){},newTypeLiteral(){});
其中A和B是接口
如果我尝试以下操作(删除TypeLiteral超类集
参数),我会得到一个java.util.Set不能用作键;未完全指定。
运行时错误
protected <T> Key<Set<T>> bindMultibinder(TypeLiteral<T> superClass) {
final Key<Set<T>> multibinderKey = Key.get(
new TypeLiteral<Set<T>>() {}, randomAnnotation);
return multibinderKey;
}
受保护密钥绑定多绑定器(TypeLiteral超类){
final Key multibinderKey=Key.get(
新的TypeLiteral(){},randomAnnotation);
返回multibinderKey;
}
如果你已经知道大部分答案,请原谅我:很难对你的水平做出假设
问题的原因是类型擦除,如您所知。为了消除类型擦除,Guice对具体的祖先使用了一个技巧,如下所示:
class Trick<T> {
T t;
}
public class GenericTest {
public static void main(String[] args) {
Trick<Set<String>> trick = new Trick<Set<String>>() {
};
// Prints "class org.acm.afilippov.GenericTest$1"
System.out.println(trick.getClass());
// Prints "org.acm.afilippov.Trick<java.util.Set<java.lang.String>>"
System.out.println(trick.getClass().getGenericSuperclass());
}
}
如您所见,类型信息现在被保留。我认为没有使用这种方法,因为即使对于这个草稿来说,它也太痛苦了。完全指定意味着所有类型参数的值都是已知的。从TypeLiteral
构造完全指定的TypeLiteral
似乎不可能使用Guice公共API。具体来说,TypeLiteral
只有两个构造函数。第一个是:
/**
* Constructs a new type literal. Derives represented class from type
* parameter.
*
* <p>Clients create an empty anonymous subclass. Doing so embeds the type
* parameter in the anonymous class's type hierarchy so we can reconstitute it
* at runtime despite erasure.
*/
@SuppressWarnings("unchecked")
protected TypeLiteral() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) MoreTypes.getRawType(type);
this.hashCode = type.hashCode();
}
我们可以按如下方式使用此构造函数:
package com.google.inject;
import java.util.Set;
import com.google.inject.internal.MoreTypes;
public class Types {
public static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> lit) {
return new TypeLiteral<Set<T>>(new MoreTypes.ParameterizedTypeImpl(null, Set.class, lit.getType()));
}
}
package com.google.inject;
导入java.util.Set;
导入com.google.inject.internal.MoreTypes;
公共类类型{
公共静态TypeLiteral集合(TypeLiteral点亮){
返回新的TypeLiteral(新的MoreTypes.ParameterizedTypeImpl(null,Set.class,lit.getType());
}
}
测试用例:
public static void main(String[] args) {
System.out.println(setOf(new TypeLiteral<String>() {}));
}
publicstaticvoidmain(字符串[]args){
System.out.println(setOf(new-TypeLiteral(){}));
}
在一个完美的世界中,Guice将提供一个公共API来完成这项任务……可能的重复项以及作为
TypeLiteral
参数传递的内容?@alf第一种方法工作正常。例如,可以这样调用它:bindMultibinder(newTypeLiteral(){},newTypeLiteral(){})代码>其中A
和B
是具体的类,而不是类型文字?另请参阅这个相关的是,看起来更容易:)谢谢,我确实希望我的练习不是唯一的方法:)@alf实现这一点的一种方法是使用com.google.inject.util.Types
,它提供了必要的API
/**
* Unsafe. Constructs a type literal manually.
*/
@SuppressWarnings("unchecked")
TypeLiteral(Type type) {
this.type = canonicalize(checkNotNull(type, "type"));
this.rawType = (Class<? super T>) MoreTypes.getRawType(this.type);
this.hashCode = this.type.hashCode();
}
package com.google.inject;
import java.util.Set;
import com.google.inject.internal.MoreTypes;
public class Types {
public static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> lit) {
return new TypeLiteral<Set<T>>(new MoreTypes.ParameterizedTypeImpl(null, Set.class, lit.getType()));
}
}
public static void main(String[] args) {
System.out.println(setOf(new TypeLiteral<String>() {}));
}