这可能是一个愚蠢的问题,但我刚刚看到一个问题,询问如何为泛型类型创建一个Type变量.共识似乎是你应该有一个返回该类型的虚方法,然后使用反射来获取它(在这种情况下他想要Map<String, String>).像这样的东西:
public Map<String, String> dummy() { throw new Error(); }
Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType();
Run Code Online (Sandbox Code Playgroud)
我的问题是,没有多少使用过反射,你不能只做以下事情:
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 };
}
};
Run Code Online (Sandbox Code Playgroud)
这会有用吗?如果没有,为什么不呢?如果它有什么危险/问题(除了能够返回一些Integer<String>明显不可能的类型之外).
当然可以,对于大多数应用来说,它可能就足够了.
但是,使用第一种方法,您将获得更精细的对象.例如,假设您type1使用第一种方法创建对象,并type2使用第二种方法.然后type1.equals(type2)返回true(因为第一个方法返回一个正确实现equals方法的对象)但是type2.equals(type1)会返回false(因为在第二个方法中,你没有重写equals-method,并且正在使用实现Object).
相同的推理适用于其他(有时是有用的方法),例如toString,hashCode等等.第二种方法不提供这些的有用实现.
如果您在项目中包含Google的Guava库(您应该;它很棒),请使用它TypeToken来获取类型.Google的Gson库(用于与JSON交互)具有类似的版本.两者都像这样使用(以获得Type代表List<String>:
Type t = new TypeToken<List<String>>(){}.getType();
Run Code Online (Sandbox Code Playgroud)
如果你不想依赖任何第三方库,你仍然可以使用匿名类型来获得具有一行代码的通用具体类型(这种技术不适用于接口,并且可能比它的摘要更麻烦类型).要获得Type代表HashMap<String, String>,请执行以下操作:
Type t = new HashMap<String, String>(){}.getClass().getGenericSuperclass();
Run Code Online (Sandbox Code Playgroud)
我已经验证,从而Type例如.equals()在Type通过创建的实例GSON的TypeToken,但还没有通过验证,同番石榴的版本TypeToken,这是我没有在时刻访问.(Guava是一个更通用的库,对于各种各样的东西非常方便,你应该可以使用它.)
小智 6
除了上述来自 Google 的库之外,还有一个来自 Apache 的库可以完成这项工作。
import org.apache.commons.lang3.reflect.TypeUtils;
...
ParameterizedType type = TypeUtils.parameterize(List.class, Double.class);
...
Run Code Online (Sandbox Code Playgroud)