为什么TypeToken在使用工厂方法的情况下捕获泛型失败?
Why does TypeToken fail to capture generic type if factory method is used?
跟进 ,似乎如果我使用工厂方法实例化 class,那么 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
为什么这不起作用,可以修复吗?
鉴于没有人愿意将他们的评论转化为正式答复,我将继续这样做:
与一样,Java只保留泛型超类的类型参数信息。由于类型参数与方法相关联(与超类相反),<E>
的运行时值不会保留。用
替换工厂方法
public static Test<MyEnum> of() {
return new Test<MyEnum>() {
};
}
会产生正确的值,但显然这违背了工厂方法的目的,因为我们被迫使用硬编码的枚举类型。
总而言之,TypeToken
在这里不起作用。保留有关类型参数信息的唯一方法是按如下方式传递 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);
}
}
根据应如何使用生成的类型,另一种选择实际上是实现 ParameterizedType。这基本上就是 TypeToken.getType() 会 return.
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;
}
};
}
跟进 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
为什么这不起作用,可以修复吗?
鉴于没有人愿意将他们的评论转化为正式答复,我将继续这样做:
与<E>
的运行时值不会保留。用
public static Test<MyEnum> of() {
return new Test<MyEnum>() {
};
}
会产生正确的值,但显然这违背了工厂方法的目的,因为我们被迫使用硬编码的枚举类型。
总而言之,TypeToken
在这里不起作用。保留有关类型参数信息的唯一方法是按如下方式传递 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);
}
}
根据应如何使用生成的类型,另一种选择实际上是实现 ParameterizedType。这基本上就是 TypeToken.getType() 会 return.
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;
}
};
}