跟进How to use TypeToken to get type parameter?,似乎如果我使用工厂方法实例化一个类,那么TypeToken
将无法再捕获泛型类型参数。
import com.google.common.reflect.TypeToken;
public class Test<E extends Enum<E>> {
private static enum MyEnum {
FIRST,
SECOND
};
private final TypeToken<E> enumType = new TypeToken<E>(getClass()) {
};
public static void main(String[] args) {
Test<MyEnum> container = new Test<MyEnum>() {
};
System.out.println("constructor: " + container.enumType.getRawType());
System.out.println("factory : " + build(MyEnum.class).enumType.getRawType());
}
public static <E extends Enum<E>> Test<E> build(Class<E> type) {
return new Test<E>() {
};
}
}
以上示例输出:
constructor: class Test$MyEnum
factory : class java.lang.Enum
为什么这不起作用,可以修复吗?
答案 0 :(得分:1)
看到没有人费心将他们的评论转换为正式答案,我将继续这样做:
作为previously discussed,Java仅保留有关通用超类的类型参数的信息。由于type-parameter与方法(而不是超类)相关联,因此不保留<E>
的运行时值。用
public static Test<MyEnum> of() {
return new Test<MyEnum>() {
};
}
将产生正确的值,但显然这会破坏工厂方法的目的,因为我们被迫使用硬编码的枚举类型。
总结一下,TypeToken
在这里工作。保留有关type-parameter的信息的唯一方法是传递Class<E>
,如下所示:
public class Test<E extends Enum<E>> {
private static enum MyEnum {
FIRST,
SECOND
};
private final Class<E> type;
public Test(Class<E> type) {
this.type = type;
}
public static void main(String[] args) {
Test<MyEnum> container = new Test<>(MyEnum.class);
System.out.println(container.type);
System.out.println(of(MyEnum.class).type);
}
public static <E extends Enum<E>> Test<E> of(Class<E> type) {
return new Test<>(type);
}
}
答案 1 :(得分:0)
根据应该如何使用生成的类型,另一个选项实际上是实现ParameterizedType。这基本上是TypeToken.getType()将返回的内容。
public static ParameterizedType parameterizedType(Class<?> rawType, Type... actualTypeArguments) {
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
@Override
public Class<?> getRawType() {
return rawType;
}
@Override
public Type getOwnerType() {
return null;
}
};
}