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

时间:2010-06-07 12:34:16

标签: java generics

这可能是一个愚蠢的问题,但我刚看到一个问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>的类型,这显然是不可能的。

4 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:7)

如果您在项目中包含Google的Guava库(您应该;它很棒),请使用其TypeToken来获取类型。 Google的Gson库(用于与JSON交互)具有类似的version。两者都是这样使用的(以获得代表Type的{​​{1}}:

List<String>

如果您不想依赖任何第三方库,您仍然可以使用匿名类型来获取具有一行代码的通用具体类型(此技术不适用于接口并且可能比抽象类型的价值更麻烦。要获得代表Type t = new TypeToken<List<String>>(){}.getType(); 的{​​{1}},请执行以下操作:

Type

我已经验证了由GsonTypeToken创建的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)

除了上面提到的来自 Google 的库之外,还有一个来自 Apache 的库可以完成这项工作。

import org.apache.commons.lang3.reflect.TypeUtils;
...
ParameterizedType type = TypeUtils.parameterize(List.class, Double.class);
...

在 GitHub here 和 Maven 工件 here 上查找代码。