2011-11-26 158 views
3

有没有简单的方法来获取祖先类的泛型参数? (而不是直接父类,如这里讨论:http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/,但层次结构中的任何祖先类获取祖先类的泛型类型

例如:假设我们有这些类:

class Class1<O,P,Q> {} 

class Class2<R,S> extends Class1<R, String, S> {} 

class Class3<U> extends Class2<List,U> {} 

class Class4<W> extends Class2<W,Set> {} 

我怎么会知道,给定一个特定的子类(例如Class3Class4)的祖先类Class1的参数的类型?请注意,所有这些信息出现在编译的时候!

例如,我知道,Class3<U>Class1会实例化为:<List, String, U>

以同样的方式,对于Class4<W>,Class1将被实例化为<W, String, Set>。所以应该可以用反思来做到这一点。请注意,我对参数的运行时值不感兴趣,而只是关于编译时数据。

感谢您的帮助!

+0

好问题...我不知道你可以从所有参数中得到参数化类型......我想过一种叫做“类型擦除”的方法......所有引用实际类型的地方在编译期间删除。如果有的话,我会对这个答案感兴趣。干杯。基思。 – corlettk

+0

嗨@corlettk,据我​​所知类型删除删除运行时类型信息,不编译有关类型的时间信息。请注意,即使这个声明不是100%真实的,因为您可以通过一些技巧来获取运行时间信息,如上面发布的链接中所讨论的。 – Sergio

+0

我刚刚阅读了链接的“教程”。有趣。我想你可以把这段代码扩展到在继承heirarchy中寻找O,P和Q的parameterizedType ......假设.getGenericSuperclass()可以在调用.getGenericSuperclass()的RESULT上调用...我会去玩(可能需要一段时间),然后发布某种答案。干杯。 – corlettk

回答

1

嗯,这是一种方法......我并不是说这是最好的(甚至是好的)方法,我只是说你可能能够适应你的需求。

package forums; 
import java.util.List; 
import java.util.Set; 
import java.lang.reflect.*; 

class Class1<O,P,Q> {} 

class Class2<R,S> extends Class1<R, String, S> {} 

class Class3<U> extends Class2<List,U> {} 

class Class4<W> extends Class2<W,Set> {} 

public class GenericTypeHeirarchy 
{ 
    public static void main(String[] args) { 
    try { 
     PrintGenericAncestorTypes(Class4.class, " "); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

    @SuppressWarnings("unchecked") 
    public static void PrintGenericAncestorTypes(Class clazz, String pad) { 
    Type supaType = clazz.getGenericSuperclass(); 
    ParameterizedType paramSupaType = null; 
    if (supaType instanceof ParameterizedType) 
     paramSupaType = (ParameterizedType) supaType; 
    if (paramSupaType == null) 
     return; // INVALID REQUEST! Parent isn't a generic type. 
    Type[] supasArgTypes = paramSupaType.getActualTypeArguments(); //actually returns TypeVariableImpl[] 
    for (Type t : supasArgTypes) { 
     // Type subinterfaces: GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType 
     if (t instanceof TypeVariable) { 
     System.out.println(pad + clazz.getName() + ": <" + t + ">"); 
     PrintGenericAncestorTypes(clazz.getSuperclass(), pad + " "); // <<<<RECURSION>>>> 
     } else { 
     System.out.println(pad + clazz.getName() + ": " + t); 
     } 
    } 
    } 

} 

编辑:

这可能仍然不是你以后......我觉得这是每一个仿制arguement类(或类名)型......但尽可能地我可以得到。我不知道如何获得一个类的类型... Type接口是空的,所以它必须被转换为某个类来获得类(或类名)...和read-arg - 类型(类java.lang.String)不知道类型的任何已知子接口(GenericArrayType,ParameterizedType,TypeVariable或WildcardType)。我推测TypeVariable<D>instanceOf TypeVariable

所以这里是我的改进版本,但我很难从哪里去。

package forums; 
import java.util.List; 
import java.util.Set; 
import java.lang.reflect.*; 

class Class1<O,P,Q> {} 

class Class2<R,S> extends Class1<R, String, S> {} 

class Class3<U> extends Class2<List,U> {} 

class Class4<W> extends Class2<W,Set> {} 

public class GenericTypeHeirarchy 
{ 
    public static void main(String[] args) { 
    try { 
     PrintGenericTypeTree(Class4.class); 
     System.out.println("--------------------------\n"); 
     PrintGenericTypeTree(Class3.class); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

    //@SuppressWarnings("unchecked") 
    public static void PrintGenericTypeTree(Class clazz) { 
    if (clazz == null || clazz == java.lang.Object.class) 
     return; 
    // 
    // class Class4<W> extends 
    // 
    System.out.print("class " + clazz.getName()); 
    TypeVariable[] argTypes = clazz.getTypeParameters(); 
    if (argTypes.length == 0) 
     return; 
    System.out.print("<"); 
    boolean first = true; 
    for (TypeVariable t : argTypes) { 
     System.out.print((first?"":", ") + t.getName()); 
     first = false; 
    } 
    System.out.print("> extends "); 
    // 
    // Class2<W,Set> 
    // 
    Class supaClass = clazz.getSuperclass(); 
    System.out.print(supaClass.getName()); 
    Type genericSupaType = clazz.getGenericSuperclass(); 
    ParameterizedType paramSupaType = null; 
    if (genericSupaType instanceof ParameterizedType) 
     paramSupaType = (ParameterizedType) genericSupaType; 
    if (paramSupaType == null) { // Parent isn't a generic type. 
     System.out.println(); 
     return; 
    } 
    Type[] supasArgTypes = paramSupaType.getActualTypeArguments(); //actually returns TypeVariableImpl[] 
    first = true; 
    System.out.print("<"); 
    for (Type t : supasArgTypes) { 
     System.out.print((first?"":", ") + t); 
     first = false; 
    } 
    System.out.println(">"); 
    PrintGenericTypeTree(supaClass); 
    } 

} 

...这里是输出...

C:\Java\home\src\forums>"C:\Program Files\Java\jdk1.6.0_16\bin\java.exe" -Xms4m -Xmx256m -enableassertions -cp c:\java\home\src;C:\Java\home\classes; forums.GenericTypeHeirarchy 

class forums.Class4<W> extends forums.Class2<W, interface java.util.Set> 
class forums.Class2<R, S> extends forums.Class1<R, class java.lang.String, S> 
class forums.Class1<O, P, Q> extends java.lang.Object 
-------------------------- 

class forums.Class3<U> extends forums.Class2<interface java.util.List, U> 
class forums.Class2<R, S> extends forums.Class1<R, class java.lang.String, S> 
class forums.Class1<O, P, Q> extends java.lang.Object 
1

伊恩•罗伯森想出了一个公平的solution。我记得它不完整,但它应该很容易让你开始。

+0

是的,从OP的代码发出的地方开始......我应该在评论它之前阅读COMPLETE文章。叹。 – corlettk