2010-01-05 2 views
3

Есть ли какой-либо путь через стандартную библиотеку или какую-то уже существующую библиотеку, чтобы определить степень зависимости между двумя классами/интерфейсами в Java?Степень связи между объектом Java и классами/интерфейсами?

Предположим, у меня есть объект и список классов/интерфейсов. Теперь я в основном хочу знать один класс этого списка, у которого есть самый короткий путь дерева наследования к этому объекту.

Я уже просмотрел пакет java.lang.reflect и Class, но не смог найти ничего, что позволило бы легко получить доступ к такой информации. Возможно, это уже часть другой библиотеки?

ответ

1

Я не знаю ничего готового к использованию.

Я бы использовал Reflection, чтобы обнаружить отношения.

Твердая часть - это кратчайший путь.

  • Вы должны определить, что именно вы хотите:

    • Например, вы поиск суперклассы первый, а затем интерфейсы?
    • Что вы решаете, когда несколько имеют одинаковую длину пути?
      Использовать по алфавиту?
      Использовать порядок обнаружения (который является случайным)? ...
  • Затем, обратите внимание на эти классы или интерфейсы в таком порядке, начиная с текущего класса, то это родительский класс (и, возможно, реализованы интерфейсы), и так далее ...

+1

Большое спасибо и за предоставление списка вещей, чтобы иметь в виду :-) –

+0

@Host Лучше всего было бы готовый к употреблению раствор. Но, не имея одного, я думал, что это может быть полезно ;-) Рад, что мы разделяем одну и ту же точку зрения :-) – KLE

1

this помогает немного. Не знаете, как получить кратчайший путь.

3

Reflection позволит вам получить родительский класс для любого заданного класса, поэтому вы можете извлечь достаточную информацию, чтобы построить себе дерево наследования, которое затем можно использовать для ответа на ваш вопрос. Я не могу придумать какой-либо встроенный механизм, который позволит вам сделать это более элегантно.

0

Этот код должен помочь вам. Как заявили другие, вы можете столкнуться с проблемами с интерфейсами, хотя, поскольку глубина наследования может быть легко одинаковой. Вам также необходимо добавить некоторую нулевую проверку и т. Д.

В этом примере FooBar3 расширяет FooBar2 расширяет FooBar.

public static void main(String[] args) { 
    List<Class<?>> l = new ArrayList<Class<?>>() {{ 
     add(FooBar2.class); 
     add(FooBar.class); 
    } }; 
    System.out.println(getClosestParent(new FooBar3(), l)); 
} 

public static Class getClosestParent(Object o, List<Class<?>> classes) { 
    List<Class<?>> related = getRelated(o, classes); 
    Collections.sort(related, new Comparator<Class<?>>() { 
     public int compare(Class<?> o1, Class<?> o2) { 
      if (o1.isAssignableFrom(o2)) { 
       return -1; 
      } else if (o2.isAssignableFrom(o1)) { 
       return 1; 
      } 
      return 0; 
     } 
    }); 
    return related.get(0); 
} 

public static List<Class<?>> getRelated(Object o, List<Class<?>> classes) { 
    List<Class<?>> filtered = new ArrayList<Class<?>>(); 
    for (Class<?> aClass : classes) { 
     if (aClass.isAssignableFrom(o.getClass())) { 
      filtered.add(aClass); 
     } 

    } 
    return filtered; 
} 
1

Я не мог не найти этот забавный проект. Вот прототип кода, который дает вам необходимую информацию. Этот код просто пытается вычислить все возможные пути наследования от данного класса к другому. Вы можете использовать это, чтобы получить все пути от исходного объекта до всех возможных классов, которые вас интересуют. Как упоминалось в других комментариях, вам может потребоваться позвонить, предпочитаете ли вы пути, которые используют интерфейсы, или нет, но надеюсь, этот код вам поможет.

public class InheritenceDepth { 

/** 
* Obtains a list of all the possible inheritance paths from the given targetClass 
* to the specified potentialAncestorClass. If the targetClass does not extend or implement 
* the potentialAncestorClass the return list will be empty. 
*/ 
public static List<InheritancePath> classInheritancePaths(Class<?> targetClass, Class<?> potentialAncestorClass){ 
    List<InheritancePath> returnList = new ArrayList<InheritancePath>(); 
    if(potentialAncestorClass.isAssignableFrom(targetClass)){ 

     if(potentialAncestorClass.equals(targetClass)){ 
      returnList.add(new InheritancePath(potentialAncestorClass)); 
     } 

     if(targetClass.getSuperclass() != null){ 
      // try superclass 
      List<InheritancePath> pathsFromSuperClass = 
       classInheritancePaths(targetClass.getSuperclass(), potentialAncestorClass); 
      if(!pathsFromSuperClass.isEmpty()){ 
       for(InheritancePath path : pathsFromSuperClass){ 
        path.add(targetClass); 
        returnList.add(path); 
       } 
      } 
     } 

     // try interfaces 
     for(Class<?> interf : targetClass.getInterfaces()){ 
      List<InheritancePath> pathsFromInterface = 
       classInheritancePaths(interf, potentialAncestorClass); 
      if(!pathsFromInterface.isEmpty()){ 
       for(InheritancePath path : pathsFromInterface){ 
        path.add(targetClass); 
        returnList.add(path); 
       } 
      } 
     } 
    } 
    return returnList; 
} 

/** 
* Represents the path from a base class to a superclass 
*/ 
public static final class InheritancePath implements Iterable<Class<?>>{ 
    private List<Class<?>> path = new ArrayList<Class<?>>(); 
    public InheritancePath(Class<?> root){ 
     path.add(root); 
    } 

    void add(Class<?> pathElement){ 
     path.add(0, pathElement); 
    } 

    public Iterator<Class<?>> iterator(){ 
     return path.iterator(); 
    } 

    public int depth(){ 
     return path.size(); 
    } 

    public String toString(){ 
     StringBuilder sb = new StringBuilder(); 
     for(int i = 0; i < path.size(); i++){ 
      sb.append(path.get(i).getName()); 
      if(i < path.size() - 1){ 
       sb.append(" -> "); 
      } 
     } 
     return sb.toString(); 
    } 
} 

public static void main(String[] args) { 
    List<InheritancePath> paths = classInheritancePaths(ConcurrentLinkedQueue.class, Collection.class); 

    for(InheritancePath path : paths){ 
     System.out.println(path); 
    } 
} 

}

+0

Большое спасибо :-) У меня уже был код для этой проблемы по большей части в моем сознании, но я просто хотел проверить , если там, возможно, была какая-то лицензионная библиотека BSD, которую я мог бы использовать, не перемещая свои собственные вещи в библиотеку многократного использования :-) –

Смежные вопросы