给定一个Type实例(可能是Class或ParameterizedType),我需要获取该类实现的特定类型的接口。如果没有泛型,这很简单,在Class实例上调用getInterfaces()就可以了。但是,即使实现的接口有自己的类型参数,也可能依赖于原始类本身的类型参数,我仍然需要这个。
一些例子,该函数应该返回Iterable< Integer>什么时候上课
class Foo implements Iterable<Integer> {}
但也必须返回Iterable&lt; String&gt;鉴于班级
class Bar<T> implements Iterable<T> {}
和表示Bar&lt; String&gt;
的ParmeterizedType使用内置反射,第三方工具等可以轻松实现此目的吗?
为了澄清,这不仅需要通过文字(Foo.class等)检索的类型实例,还需要通过可以包含应用类型参数的反射返回的类型实例,例如通过方法反射返回的返回类型< / p>
static Bar<String> magic() { ... }
这将是引用原始Bar类和String类型参数的ParameterizedType。
答案 0 :(得分:2)
您应该查看Google Guava TypeToken
课程:http://code.google.com/p/guava-libraries/wiki/ReflectionExplained
它提供了用于在各种上下文中解析类型的复杂机制。并且如果我正确理解了您的问题,那么TypeToken#resolveType(Type)
方法之类的内容可能与您正在寻找的内容接近:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;
import com.google.common.reflect.TypeToken;
class Foo implements Iterable<Integer> {
@Override
public Iterator<Integer> iterator()
{
return null;
}
}
class Bar<T> implements Iterable<T> {
@Override
public Iterator<T> iterator()
{
return null;
}
}
public class TypeParameterTest
{
public static void main(String[] args) throws Exception
{
Type i0 = getInterface(Foo.class, 0);
System.out.println("First interface implemented by Foo: "+i0);
Method method = TypeParameterTest.class.getDeclaredMethod("magic");
Type returnType = method.getGenericReturnType();
System.out.println("Magic method return type: "+returnType);
Type i1 = getInterface(returnType, 0);
System.out.println("First interface implemented by Bar<String>: "+i1);
}
private static Type getInterface(Type type, int interfaceIndex)
{
TypeToken<?> typeToken = TypeToken.of(type);
Class<?> c = typeToken.getRawType();
Type[] interfaces = c.getGenericInterfaces();
if (interfaces.length == 0)
{
return null;
}
Type i = interfaces[interfaceIndex];
return typeToken.resolveType(i).getType();
}
public static Bar<String> magic() { return null; }
}
这里的输出是
First interface implemented by Foo: java.lang.Iterable<java.lang.Integer>
Magic method return type: Bar<java.lang.String>
First interface implemented by Bar<String>: java.lang.Iterable<java.lang.String>
答案 1 :(得分:0)
当类型为硬编码时,您可以使用反射,因为它是特定类型的子类。这里的类型存储在类信息中。
如果您使用反射,则可以看到Foo
扩展Iterable<String>
,但如果您有Bar<String>
,则由于类型擦除而在运行时这只是Bar
你看,Bar
扩展Iterable<T>
如果您具有参数化的泛型类型,则不会在任何地方记录,因为它在运行时没有操作。如果您需要此类型,则需要将其另存为附加字段。
e.g。有一个类Collections.CheckedMap在运行时检查类型,它就像这样开始
private static class CheckedMap<K,V>
implements Map<K,V>, Serializable
{
private static final long serialVersionUID = 5742860141034234728L;
private final Map<K, V> m;
final Class<K> keyType;
final Class<V> valueType;
答案 2 :(得分:0)
以下是使用ParameterizedType
的示例import java.lang.reflect.*;
public class Foo {
static class Bar<T> {
}
static class SubBar extends Bar<Integer> {
}
public static void main(String argv[]) {
ParameterizedType pt = (ParameterizedType)SubBar.class.getGenericSuperclass();
Type[] t = pt.getActualTypeArguments();
for (int i=0;i<t.length;i++) {
System.out.println(t[i]);
}
}
}
答案 3 :(得分:0)
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
public class Dummy implements Iterable<Integer> {
public static void main(String args[]) throws Exception {
Dummy d = new Dummy();
Type[] genericInterfaces = Dummy.class.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) genericInterface).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("Generic type: " + genericType);
}
}
}
}
@Override
public Iterator<Integer> iterator() {
// TODO Auto-generated method stub
return null;
}
}