这可能是一个愚蠢的问题,但我刚看到一个问how to create a Type variable for a generic type的问题。共识似乎是你应该有一个返回该类型的虚方法,然后使用反射来获取它(在这种情况下,他想要Map<String, String>
)。像这样:
public Map<String, String> dummy() { throw new Error(); }
Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType();
我的问题是,没有那么多使用反射,你不能只做一些像:
Type mapStringString = new ParameterizedType() {
public Type getRawType() {
return Map.class;
}
public Type getOwnerType() {
return null;
}
public Type[] getActualTypeArguments() {
return new Type[] { String.class, String.class };
}
};
这会有用吗?如果没有,为什么不呢?如果它有什么危险/问题(除了能够返回一些类似Integer<String>
的类型,这显然是不可能的。
答案 0 :(得分:7)
当然可以,对于大多数应用来说,它可能就足够了。
但是,使用第一种方法,您将获得更精细的对象。例如,假设您使用第一种方法创建对象type1
,使用第二种方法创建type2
。然后type1.equals(type2)
将返回true(因为第一个方法返回一个正确实现equals方法的对象)但type2.equals(type1)
将返回false(因为在第二个方法中,您没有覆盖equals方法,并正在使用Object
)的实现。
相同的推理适用于其他(有时是有用的方法),例如toString
,hashCode
等。第二种方法不提供这些方法的有用实现。
答案 1 :(得分:7)
如果您在项目中包含Google的Guava库(您应该;它很棒),请使用其TypeToken
来获取类型。 Google的Gson库(用于与JSON交互)具有类似的version。两者都是这样使用的(以获得代表Type
的{{1}}:
List<String>
如果您不想依赖任何第三方库,您仍然可以使用匿名类型来获取具有一行代码的通用具体类型(此技术不适用于接口并且可能比抽象类型的价值更麻烦。要获得代表Type t = new TypeToken<List<String>>(){}.getType();
的{{1}},请执行以下操作:
Type
我已经验证了由Gson的TypeToken
创建的HashMap<String, String>
实例Type t = new HashMap<String, String>(){}.getClass().getGenericSuperclass();
Type
实例,但Guava {{}}} 3}} TypeToken
的版本,目前我无法访问。 (Guava是一个更通用的库,对于各种各样的东西非常方便,你应该可以使用它。)
答案 2 :(得分:2)
实际上,我认为最简单的方法(==最少代码)是扩展您感兴趣的类型的虚拟接口,然后从其类中getGenericInterfaces()[0]
(如果你使用getGenericSuperclass()
“对课堂感兴趣”:
private interface MapStringString extends Map<String, String> {}
private static ParameterizedType mapStringString(){
return (ParameterizedType) MapStringString.class.getGenericInterfaces()[0];
}
但是,它不能很好地扩展,因为你必须为你想要表示的每个ParameterizedType
创建一个新类。我不明白为什么你的实现不会这样做(除非在某处有缩小的演员阵容),它确实具有吸引人的好处,你可以让它重复使用。
答案 3 :(得分:1)