保持通用参数的关联类

时间:2015-03-21 16:56:58

标签: java generics

我有一个带有泛型参数的类,由于各种原因,我需要与该参数关联的具体类,所以我想接受它作为构造函数的一部分,例如:

public class Foo<T> {
    private final Class<T> clazz;
    public Foo(Class<T> clazz) {
        this.clazz = clazz;
    }
}

我还有其他一些类,我想用它来构造它,也可以参数化,例如:

public class MyObj<T> { /* stuff */ }

当我尝试使用Foo<T>创建MyObj时,我似乎无法计算出要编译的参数。例如这失败了:

Foo<MyObj<?>> foo = new Foo<MyObj<?>>(MyObj.class);

发生编译时错误,如:

  

构造函数Foo<MyObj<?>>(Class<MyObj>)未定义

同样,当我为MyObj提供具体类型时,事情仍然失败:

Foo<MyObj<String>> foo = new Foo<MyObj<String>>(MyObj.class);

发生编译时错误,如:

  

构造函数Foo<MyObj<String>>(Class<MyObj>)未定义

我怀疑Foo的构造函数参数在我的Foo定义或我的构造函数调用中是不正确的,但我不确定如何修改类型参数。< / p>

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

Class无法表示参数化类型。相同的Class对象将MyObj<String>表示为MyObj<Integer>(或者更确切地说没有MyObj<String>类型的对象,只有MyObj类型的对象,泛型是编译时功能,它们不会在运行时定义对象。

如果你只是一个非通用的

class MyObj {}

你可以简单地做

Foo<MyObj> foo = new Foo<>(MyObj.class);

但是,由于您的类型是通用的,并且您似乎想要维护其类型参数的类型,因此您需要更进一步。你需要类型代币。

Guava提供了一个可以使用的TypeToken课程。您必须将Foo更改为

class Foo<T> {
    final Type type;

    public Foo(Type type) {
        this.type = type;
    }
}

然后

Foo<MyObj<String>> foo = new Foo<MyObj<String>>(new TypeToken<MyObj<String>>() {}.getType());

现在,如果您打印出type,就会看到

com.example.MyObj<java.lang.String>

如果将其强制转换为ParameterizedType,则可以检索其参数化。

但请注意,您无法在此处获得类型安全性。你可能不小心写了

Foo<MyObj<String>> foo = new Foo<MyObj<String>>(new TypeToken<MyObj<Integer>>() {}.getType());

它会编译好。

答案 1 :(得分:0)

我会这样做:

  Foo<MyObj> foo = new Foo<MyObj>(MyObj.class);

如果我真的知道你试图解决的更高级问题是什么,我可以给出更好的建议。但我必须与之合作的是&#34; Foo&#34;和&#34; MyObj&#34;