使用匿名类创建参数化类型对象

这可能是一个愚蠢的问题,但我刚刚看到一个问题,询问如何为generics类型创建一个Type变量 。 共识似乎是你应该有一个返回该类型的虚方法,然后使用reflection来获取它(在这种情况下,他想要Map )。 像这样的东西:

 public Map dummy() { throw new Error(); } Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType(); 

我的问题是,没有多少使用reflection,你不能只做以下事情:

 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类型,这显然是不可能的)。

当然可以,对于大多数应用来说,它可能就足够了。

但是,使用第一种方法,您将获得更精细的对象。 例如,假设您使用第一种方法创建对象type1 ,使用第二种方法创建type2 。 然后type1.equals(type2)将返回true(因为第一个方法返回一个正确实现equals方法的对象)但是type2.equals(type1)将返回false(因为在第二个方法中,你没有重写equals -method,并且正在使用Object的实现)。

相同的推理适用于其他(有时是有用的方法),如toStringhashCode等。第二种方法不提供这些的有用实现。

如果您在项目中包含Google的Guava库(您应该;它很棒),请使用其TypeToken来获取类型。 Google的Gson库(用于与JSON交互)具有类似的版本 。 两者都像这样使用(获取表示ListType

 Type t = new TypeToken>(){}.getType(); 

如果你不想依赖任何第三方库,你仍然可以使用匿名类型来获得具有一行代码的通用具体类型(这种技术不适用于接口,并且可能比它的摘要更麻烦类型)。 要获取表示HashMapType ,请执行以下操作:

 Type t = new HashMap(){}.getClass().getGenericSuperclass(); 

我已经validation了生成的Type实例.equals()是由Gson的TypeToken创建的Type实例,但是对于Guava的TypeToken版本没有validation相同,我目前无法访问它。 (Guava是一个更通用的库,对于各种各样的东西非常方便,你应该可以使用它。)

实际上,我认为执行此操作的最简单方法(==最少代码)将是扩展您感兴趣的类型的虚拟接口,然后从其类中获取getGenericInterfaces()[0] getGenericSuperclass()如果您感兴趣,请使用getGenericSuperclass()一类):

 private interface MapStringString extends Map {} private static ParameterizedType mapStringString(){ return (ParameterizedType) MapStringString.class.getGenericInterfaces()[0]; } 

但是,它不能很好地扩展,因为您必须为要表示的每个ParameterizedType创建一个新类。 我不明白为什么你的实现不会这样做(除非在某处有缩小的演员),它确实具有吸引人的好处,你可以使它可重用。