java獲取全部子類或接口的全部實現


在JAVA中,獲取一個類的全部父類是比較簡單的,只需要通過反射(Class的getSuperclass()方法)即可。然而,如果想獲得一個類的所有子類,或者獲得實現某一個接口的所有實現類,相對比較麻煩。

用過Eclipse的開發人員都知道,通過F4鍵或(Ctrl+T組合鍵)可以查到指定類的類層次結構。仔細想一下該快捷鍵的實現原理,或許可以找到一個可行的設計思路。

首先,需要確定一個前提是,尋找所有子類,必須先指定搜索的文件范圍。打個比方,要尋找一個古人的所有后代成員,必須設置查找的地理范圍是在中國內,否則就無從入手。

結合實際的項目部署環境,查找子類的方法需要有兩種方式。第一種,在開發環境,可以直接遍歷指定范圍下的所有源代碼文件,再結合反射的知識;第二種,假設項目已經打成jar包,則只能通過jar包獲得所有類文件。

下面給出具體的代碼實現

1.若是開發環境,則通過遞歸查找指定目錄下的類文件的全路徑,代碼如下

 1 /**
 2  * 遞歸查找指定目錄下的類文件的全路徑
 3  *
 4  * @param baseFile 查找文件的入口
 5  * @param fileList 保存已經查找到的文件集合
 6  */
 7 public static void getSubFileNameList(File baseFile, List<String> fileList) {
 8     if (baseFile.isDirectory()) {
 9         File[] files = baseFile.listFiles();
10         for (File tmpFile : files) {
11             getSubFileNameList(tmpFile, fileList);
12         }
13     }
14     String path = baseFile.getPath();
15     if (path.endsWith(".java")) {
16         String name1 = path.substring(path.indexOf("src") + 4, path.length());
17         String name2 = name1.replaceAll("\\\\", ".");
18         String name3 = name2.substring(0, name2.lastIndexOf(".java"));
19         fileList.add(name3);
20     }
21 }

獲取根路徑方法 final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());

 

2.若是jar包環境,則可以通過JarFile這個工具類,獲得所有全部類信息

 1 /**
 2  * 從jar包讀取所有的class文件名
 3  */
 4 private static List<String> getClassNameFrom(String jarName) {
 5     List<String> fileList = new ArrayList<String>();
 6     try {
 7         JarFile jarFile = new JarFile(new File(jarName));
 8         Enumeration<JarEntry> en = jarFile.entries(); // 枚舉獲得JAR文件內的實體,即相對路徑  
 9         while (en.hasMoreElements()) {
10             String name1 = en.nextElement().getName();
11             if (!name1.endsWith(".class")) {//不是class文件
12                 continue;
13             }
14             String name2 = name1.substring(0, name1.lastIndexOf(".class"));
15             String name3 = name2.replaceAll("/", ".");
16             fileList.add(name3);
17         }
18     } catch (IOException e) {
19         e.printStackTrace();
20     }
21 
22     return fileList;
23 }

 

3.從前兩步可以得到所有子類或所有接口實現類的類路徑信息,有了類的全路徑,就可以通過反射拿到類的信息,用來判斷是否滿足條件

 1 /**
 2  * 判斷一個類是否繼承某個父類或實現某個接口
 3  */
 4 public static boolean isChildClass(String className, Class parentClazz) {
 5     if (className == null) return false;
 6 
 7     Class clazz = null;
 8     try {
 9         clazz = Class.forName(className);
10         if (Modifier.isAbstract(clazz.getModifiers())) {//抽象類忽略
11             return false;
12         }
13         if (Modifier.isInterface(clazz.getModifiers())) {//接口忽略
14             return false;
15         }
16     } catch (Exception e) {
17         e.printStackTrace();
18         return false;
19     }
20     return parentClazz.isAssignableFrom(clazz);
21 
22 }

 

4.寫幾個簡單的測試類,用來說明問題

1 package bean;
2 
3 public abstract class Animal {
4     public abstract void eat();
5     public abstract void walk();
6 }
 1 package bean;
 2  
 3 public class Cat extends Animal{
 4  
 5     @Override
 6     public void eat() {
 7         System.err.println("小貓吃東西");
 8     }
 9  
10     @Override
11     public void walk() {
12         System.err.println("小貓走路");
13     }
14  
15 }
 1 package bean;
 2  
 3 public class Dog extends Animal{
 4  
 5     @Override
 6     public void eat() {
 7         System.err.println("小狗吃東西");
 8     }
 9  
10     @Override
11     public void walk() {
12         System.err.println("小狗走路");
13     }
14  
15 }
 1 package bean;
 2  
 3 public class Person {
 4     private String name;
 5     private int age;
 6     
 7     public Person(){
 8         
 9     }
10     public Person(String name, int age) {
11         super();
12         this.name = name;
13         this.age = age;
14     }
15  
16     public void sayHello(){
17         System.err.println("hello,i am " + this.name);
18     }
19 }

 

5.入口方法,打印輸出結果(jar包可直接使用Eclipse導出可執行jar文件)

 1     List<String> fileList = new ArrayList<String>();
 2 
 3     File baseFile = new File(getSrcPath() + File.separator + "src" + File.separator + "bean");
 4         if(baseFile.exists()){//開發環境,讀取源文件
 5                 getSubFileNameList(baseFile,fileList);
 6                 }else{//jar包環境
 7                 fileList=getClassNameFrom("server.jar");
 8                 }
 9                 System.err.println("Animal類的所有子類有");
10                 for(String name:fileList){
11                 if(isChildClass(name,Animal.class))
12         System.err.println(name);
13         }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM