Получение классов универсальных типов класса предков - PullRequest
3 голосов
/ 26 ноября 2011

Есть ли простой способ получить общие параметры класса предка? (не непосредственный родительский класс, как обсуждалось здесь: 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> {}

Как узнать, учитывая определенный класс-потомок (например, Class3 или Class4), тип параметров класса-предка Class1? Обратите внимание, что вся эта информация присутствует во время компиляции!

Например, я знаю, что для Class3<U> будет создан экземпляр Class1 с: <List, String, U>.

Таким же образом, для Class4<W>, Class1 будет создан с <W, String, Set>. Так что должно быть возможно сделать это с отражением. Обратите внимание, что меня интересуют не значения параметров времени выполнения, а просто данные времени компиляции.

Спасибо за вашу помощь !!

Ответы [ 2 ]

1 голос
/ 26 ноября 2011

Ян Робертсон предложил справедливое решение .Насколько я помню, она не завершена, но она должна легко начать работу.

1 голос
/ 26 ноября 2011

Ну, вот подход ... Я не говорю, что это лучший (или даже хороший) подход, я просто говорю, что вы могли бы адаптировать его к вашим потребностям.

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);
      }
    }
  }

}

РЕДАКТИРОВАТЬ:

Это, вероятно, все еще не то, что вы ищете ... который, я думаю, будет классом (или именем класса) для каждого общего типа аргумента ... но это насколько я могу получить. Я не знаю, как получить класс для типа ... Интерфейс типа пуст, поэтому его нужно привести к чему-то, чтобы получить класс (или имя-класса) из ... и read-arg -types (например, 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...