JAVA-获取实现了指定接口类的所有实现类或继承了指定类的所有子类

实际编程过程中,我们可能遇到这样的问题,就是获取实现了指定接口类的所有实现类。
本工具类就提供了这样的功能。下面是工具类的详细解析:

/**
 * 查找指定路径下面实现指定接口的全部类
 * @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中可以获取到所有继承了指定类的所有子类!!!

本人测试完成,完全满足需求!!!
如果有疑问,请留言或评论!!

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值