2010-01-05 4 views
3

표준 라이브러리 나 이미 존재하는 라이브러리를 통해 Java의 두 클래스/인터페이스 간의 관계 정도를 확인할 수 있습니까?Java 객체와 클래스/인터페이스 간의 관계도?

개체와 클래스/인터페이스 목록이 있다고 가정 해 보겠습니다. 이제는 기본적으로이 개체에 대한 가장 짧은 상속 트리 경로가있는 해당 목록의 한 클래스를 알고 싶습니다.

이미 java.lang.reflect 패키지와 클래스를 살펴 보았지만 이와 같은 정보에 쉽게 액세스 할 수있는 것을 찾을 수 없었습니다. 아마도 이미 다른 도서관의 일부일까요?

답변

1

사용할 준비가 된 제품이 없습니다.

리플렉션을 사용하여 관계를 발견했습니다.

단단한 부분이 최단 경로입니다. 먼저 다음 인터페이스 상위 클래스를 검색 할 예를 들어,

  • :

    • 당신은 당신이 원하는 정확하게 정의 할 필요가?

    • 여러 경로의 경로 길이가 같은 경우 어떻게 결정합니까?
      알파벳순으로 사용 하시겠습니까?
      발견 순서 (무작위)를 사용 하시겠습니까? ...
    • 그런
  • 은 순서대로 이러한 클래스 나 인터페이스를 찾아, 현재의 클래스로 시작, ... 등등 그것은 부모 클래스 (그리고 아마도 인터페이스를 구현), 그리고

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

}는 대단히 및 즉시 사용 가능한 솔루션을했을 것이다 가장 좋은 @Host –

+0

:-) 염두에 두어야 할 것들의 목록을 제공해 주셔서 감사합니다. 하지만 하나가 부족해서 유용 할 수 있다고 생각했습니다 .--) 우리가 똑같은 견해를 공유하고 있습니다 :-) – KLE

1

this 조금 도움이됩니다. 최단 경로를 얻는 방법을 모르겠습니다.

3

Reflection을 사용하면 주어진 클래스에 대한 상위 클래스를 얻을 수 있으므로 상속 트리를 구축 할 수있는 충분한 정보를 추출 할 수 있으므로 질문에 대답 할 수 있습니다. 나는 당신이 더 이상 그것을 우아하게 할 수있는 내장 된 메커니즘을 생각할 수 없다.

0

이 코드는 여러분을 가까이에있게 할 것입니다. 다른 사람들이 말했듯이 상속 깊이가 쉽게 같을 수 있기 때문에 인터페이스에 문제가 발생할 수 있습니다. 또한 null 검사 등을 추가해야합니다.

이 예제에서 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

재미있는 소리로 들리는 프로젝트를 찾지 못했습니다. 필요한 정보를 제공하는 프로토 타입 코드가 있습니다. 이 코드는 주어진 클래스에서 다른 클래스로 가능한 모든 상속 경로를 계산하려고 시도합니다. 이것을 사용하여 소스 객체에서 관심있는 모든 가능한 클래스로 모든 경로를 가져올 수 있습니다. 다른 주석에서 언급했듯이 인터페이스를 사용하는지 아닌지를 선호하는 경로에 대해 호출해야 할 수도 있습니다. 이 코드가 도움이되기를 바랍니다.

+0

대단히 고마워요 :-) 나는 이미 그 문제에 대한 코드를 내 마음 속에서 가지고 있었지만 그저 체크 아웃하고 싶었습니다. , BSD 라이센스 라이브러리가 있다면 재사용 가능한 라이브러리에 내 물건을 옮기지 않고 사용할 수 있습니다 :-) –

관련 문제