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>() {}));
}