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

And*_*anu 11 java generics

这可能是一个愚蠢的问题,但我刚刚看到一个问题,询问如何为泛型类型创建一个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>明显不可能的类型之外).

aio*_*obe 7

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

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

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


Mat*_*olm 7

如果您在项目中包含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通过创建的实例GSONTypeToken,但还没有通过验证,同番石榴的版本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)

在 GitHub 上查找代码,在此处查找Maven 工件。