为通用参数保持关联 class
Keeping associated class for a generic parameter
我有一些带有通用参数的 class,出于各种原因,我需要与该参数关联的具体 class,所以我想接受它作为构造函数的一部分,例如:
public class Foo<T> {
private final Class<T> clazz;
public Foo(Class<T> clazz) {
this.clazz = clazz;
}
}
我还有一些其他的 class,我想用它来构造它,它也被参数化了,例如:
public class MyObj<T> { /* stuff */ }
当我尝试用 MyObj
创建 Foo<T>
时,我似乎无法计算出参数来编译。例如这失败了:
Foo<MyObj<?>> foo = new Foo<MyObj<?>>(MyObj.class);
编译时错误如:
The constructor Foo<MyObj<?>>(Class<MyObj>)
is undefined
同样,当我为 MyObj
提供具体类型时,事情仍然失败:
Foo<MyObj<String>> foo = new Foo<MyObj<String>>(MyObj.class);
编译时错误如:
The constructor Foo<MyObj<String>>(Class<MyObj>)
is undefined
我怀疑 Foo
的构造函数参数在我对 Foo
的定义中或在我对构造函数的调用中不正确,但我不确定如何修改类型参数。
我该如何解决这个问题?
Class
不能表示参数化类型。同一个 Class
对象将 MyObj<String>
表示为 MyObj<Integer>
(或者更确切地说,没有 MyObj<String>
类型的对象,只有 MyObj
类型的对象,泛型是一个编译时特性,它们不在运行时定义对象。
如果你只是有一个非通用的
class MyObj {}
你可以简单地做
Foo<MyObj> foo = new Foo<>(MyObj.class);
但是由于您的类型是泛型的,并且您似乎想要维护其类型参数的类型,因此您需要更进一步。您需要类型标记。
Guava 提供了TypeToken
class你可以使用。您必须将 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());
编译成功。
我会这样做:
Foo<MyObj> foo = new Foo<MyObj>(MyObj.class);
如果我真的知道你试图解决的更高层次的问题是什么,我可以提供更好的建议。但我所要做的就是 "Foo" 和 "MyObj"
我有一些带有通用参数的 class,出于各种原因,我需要与该参数关联的具体 class,所以我想接受它作为构造函数的一部分,例如:
public class Foo<T> {
private final Class<T> clazz;
public Foo(Class<T> clazz) {
this.clazz = clazz;
}
}
我还有一些其他的 class,我想用它来构造它,它也被参数化了,例如:
public class MyObj<T> { /* stuff */ }
当我尝试用 MyObj
创建 Foo<T>
时,我似乎无法计算出参数来编译。例如这失败了:
Foo<MyObj<?>> foo = new Foo<MyObj<?>>(MyObj.class);
编译时错误如:
The constructor
Foo<MyObj<?>>(Class<MyObj>)
is undefined
同样,当我为 MyObj
提供具体类型时,事情仍然失败:
Foo<MyObj<String>> foo = new Foo<MyObj<String>>(MyObj.class);
编译时错误如:
The constructor
Foo<MyObj<String>>(Class<MyObj>)
is undefined
我怀疑 Foo
的构造函数参数在我对 Foo
的定义中或在我对构造函数的调用中不正确,但我不确定如何修改类型参数。
我该如何解决这个问题?
Class
不能表示参数化类型。同一个 Class
对象将 MyObj<String>
表示为 MyObj<Integer>
(或者更确切地说,没有 MyObj<String>
类型的对象,只有 MyObj
类型的对象,泛型是一个编译时特性,它们不在运行时定义对象。
如果你只是有一个非通用的
class MyObj {}
你可以简单地做
Foo<MyObj> foo = new Foo<>(MyObj.class);
但是由于您的类型是泛型的,并且您似乎想要维护其类型参数的类型,因此您需要更进一步。您需要类型标记。
Guava 提供了TypeToken
class你可以使用。您必须将 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());
编译成功。
我会这样做:
Foo<MyObj> foo = new Foo<MyObj>(MyObj.class);
如果我真的知道你试图解决的更高层次的问题是什么,我可以提供更好的建议。但我所要做的就是 "Foo" 和 "MyObj"