是否有某种方法可以通过标准库或某些现有的库来确定Java中两个类/接口之间的关系程度?
假设我有一个对象和一个类/接口列表。现在我基本上想知道该列表的一个类,它具有此对象的最短继承树路径。
我已经查看了java.lang.reflect包和Class,但实际上找不到任何可以轻松访问此类信息的内容。那可能已经是另一个图书馆的一部分了吗?
答案 0 :(得分:3)
Reflection将允许您获取任何给定类的父类,因此您可以提取足够的信息来构建自己的继承树,然后您可以使用它来回答您的问题。我想不出任何可以让你更优雅的内置机制。
答案 1 :(得分:1)
this有所帮助。 不知道如何获得最短的路径。
答案 2 :(得分:1)
我不知道有什么可以使用的。
我会用反射来发现关系。
困难的部分是最短路径。
您必须定义您想要的内容:
然后,按顺序查找这些类或接口,从当前类开始,然后是父类(以及可能实现的接口),依此类推......
答案 3 :(得分: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);
}
}
}
答案 4 :(得分: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;
}