標籤:指定介面的所有實作類別 指定父類的所有子類 介面類 父類
實際編程過程中,我們可能遇到這樣的問題,就是擷取實現了指定介面類的所有實作類別。
本工具類就提供了這樣的功能。下面是工具類的詳細解析:
/** * 尋找指定路徑下面實現指定介面的全部類 * @author longyin * @author 部落格地址:http://blog.csdn.net/u010156024 * 如果大家有什麼問題或疑問,歡迎留言或評論,謝謝!! */public class ClassUtil { @SuppressWarnings({ "rawtypes", "unchecked" }) public static ArrayList<Class> getAllClassByInterface(Class clazz){ ArrayList<Class> list = new ArrayList<>(); //判斷是否是一個介面 if (clazz.isInterface()) { try { ArrayList<Class> allClass = getAllClass(clazz.getPackage().getName()); /** * 迴圈判斷路徑下的所有類是否實現了指定的介面 * 並且排除介面類自己 */ for (int i = 0; i < allClass.size(); i++) { /** * 判斷是不是同一個介面 * 該方法的解析,請參考部落格: * http://blog.csdn.net/u010156024/article/details/44875195 */ if (clazz.isAssignableFrom(allClass.get(i))) { if (!clazz.equals(allClass.get(i))) {//自身並不加進去 list.add(allClass.get(i)); }else { } } } } catch (Exception e) { System.out.println("出現異常"); } }else { //如果不是介面不作處理 } return list; } /** * 從一個指定路徑下尋找所有的類 * @param name */ @SuppressWarnings("rawtypes") private static ArrayList<Class> getAllClass(String packagename) { ArrayList<Class> list = new ArrayList<>(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packagename.replace(‘.‘, ‘/‘); try { ArrayList<File> fileList = new ArrayList<>(); /** * 這裡面的路徑使用的是相對路徑 * 如果大家在測試的時候擷取不到,請理清目前工程所在的路徑 * 使用相對路徑更加穩定! * 另外,路徑中切不可包含空格、特殊字元等! * 本人在測試過程中由於空格,吃了大虧!!! */ Enumeration<URL> enumeration = classLoader.getResources("../bin/"+path); while (enumeration.hasMoreElements()) { URL url = enumeration.nextElement(); fileList.add(new File(url.getFile())); } for (int i = 0; i < fileList.size(); i++) { list.addAll(findClass(fileList.get(i),packagename)); } } catch (IOException e) { e.printStackTrace(); } return list; } /** * 如果file是檔案夾,則遞迴調用findClass方法,或者檔案夾下的類 * 如果file本身是類檔案,則加入list中進行儲存,並返回 * @param file * @param packagename * @return */ @SuppressWarnings("rawtypes") private static ArrayList<Class> findClass(File file,String packagename) { ArrayList<Class> list = new ArrayList<>(); if (!file.exists()) { return list; } File[] files = file.listFiles(); for (File file2 : files) { if (file2.isDirectory()) { assert !file2.getName().contains(".");//添加斷言用於判斷 ArrayList<Class> arrayList = findClass(file2, packagename+"."+file2.getName()); list.addAll(arrayList); }else if(file2.getName().endsWith(".class")){ try { //儲存的類檔案不需要尾碼.class list.add(Class.forName(packagename + ‘.‘ + file2.getName().substring(0, file2.getName().length()-6))); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return list; }}
上面方法,大家在運行測試的時候一定記得更改路徑。一定以當前功能檔案所在的路徑下使用相對路徑進行更新,是路徑執行可執行檔.class檔案。
上面的類中的public方法是提供給外界進行調用的,該方法裡面有一個isInterface的判斷,加入了該判斷的話,就只能擷取所有實現了指定介面的類,那麼要擷取繼承了指定類的所有類怎麼做呢?
非常簡單,不加這個判斷就可以了。
所有上面的public方法更改如下:
@SuppressWarnings({ "rawtypes", "unchecked" }) public static ArrayList<Class> getAllClassByInterface(Class clazz){ ArrayList<Class> list = new ArrayList<>(); //擷取指定介面的實作類別 if (clazz.isInterface()) { try { ArrayList<Class> allClass = getAllClass(clazz.getPackage().getName()); /** * 迴圈判斷路徑下的所有類是否實現了指定的介面 * 並且排除介面類自己 */ for (int i = 0; i < allClass.size(); i++) { /** * 判斷是不是同一個介面 * isAssignableFrom該方法的解析,請參考部落格: * http://blog.csdn.net/u010156024/article/details/44875195 */ if (clazz.isAssignableFrom(allClass.get(i))) { if (!clazz.equals(allClass.get(i))) {//自身並不加進去 list.add(allClass.get(i)); }else { } } } } catch (Exception e) { System.out.println("出現異常"); } //如果不是介面,則擷取它的所有子類 }else{ try { ArrayList<Class> allClass = getAllClass(clazz.getPackage().getName()); /** * 迴圈判斷路徑下的所有類是否繼承了指定類 * 並且排除父類自己 */ for (int i = 0; i < allClass.size(); i++) { /** * isAssignableFrom該方法的解析,請參考部落格: * http://blog.csdn.net/u010156024/article/details/44875195 */ if (clazz.isAssignableFrom(allClass.get(i))) { if (!clazz.equals(allClass.get(i))) {//自身並不加進去 list.add(allClass.get(i)); }else { } } } } catch (Exception e) { System.out.println("出現異常"); } } return list; }
在else中可以擷取到所有繼承了指定類的所有子類!!!
本人測試完成,完全滿足需求!!!
如果有疑問,請留言或評論!!
JAVA-擷取實現了指定介面類的所有實作類別或繼承了指定類的所有子類