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中可以获取到所有继承了指定类的所有子类!!!

本人测试完成,完全满足需求!!!

如果有疑问,请留言或评论!!

时间: 2024-10-21 23:10:09

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

java 获取今天、昨天、本周、本月、本年的时间范围的工具类

import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; /** * 时间范围工具类 * * @author zwq * */ public class TimeFrameUtil { /** * 获取今天的时间范围 * @return 返回长度为2的字符串集合,如:[2017-11-03 00:00:00, 2017-11-03

JAVA的核心概念:接口(interface)

接口与类属于同一层次,实际上,接口是一种特殊的抽象类. 如:    interface IA{ }  public interface: 公开接口  与类相似,一个文件只能有一个public接口,且与文件名相同. 在一个文件中不可同时定义一个public接口和一个public类. 一个接口中,所有方法为公开.抽象方法:所有的属性都是公开.静态.常量. 一个类实现一个接口的格式: class IAImple implements IA{ };   一个类实现接口,相当于它继承一个抽象类. 类必须实

Java 8新特性之接口改善(八恶人-1)

Daisy Donergue 多莫歌·黛西 "By woman, you mean her?" 她也能叫女人? Java 8在13年9月发布,写这篇博文的时间已经是17年12月份了.来的有点晚,但是有必要补一下1.8的特性. 一.基本介绍 Java 8中接口里已经完全可以定义静态方法了. 举一个比较普遍的例子就是在java类库中, 对于一些接口如Foo, 都会有一个有静态方法的工具类Foos 来生成或者配合Foo对象实例来使用. 既然静态方法可以存在于接口当中, 那么大多数情况下 Fo

基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------&gt; 可以返回派生类对象的引用或指针

您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. 百度和网页 http://bbs.csdn.net/topics/380238133 的作者无关,不对其内容负责.百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面. 首页 精选版块 移动开发 iOS Android Qt WP 云计算 IaaS Pass/SaaS 分布式计算/Hadoop J

ES6里关于类的拓展(二):继承与派生类

继承与派生类 在ES6之前,实现继承与自定义类型是一个不小的工作.严格意义上的继承需要多个步骤实现 function Rectangle(length, width) { this.length = length; this.width = width; } Rectangle.prototype.getArea = function() { return this.length * this.width; }; function Square(length) { Rectangle.call(

OOP3(继承中的类作用域/构造函数与拷贝控制/继承与容器)

当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内.如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义 在编译时进行名字查找: 一个对象.引用或指针的静态类型决定了该对象的哪些成员是可见的,即使静态类型与动态类型不一致: 1 #include <iostream> 2 using namespace std; 3 4 class A{ 5 public: 6 // A(); 7 // ~A(); 8 ostream& print(ost

Java泛型:泛型的定义(类、接口、对象)、使用、继承

地址   http://blog.csdn.net/lirx_tech/article/details/51570138 1. 设计泛型的初衷: 1) 主要是为了解决Java容器无法记忆元素类型的问题: i. 由于Java设计之初并不知道会往容器中存放什么类型的元素,因此元素类型都设定为Object,这样就什么东西都能放了! ii. 但是这样设计有明显的缺点: a. 取出元素的时候必须进行强制类型转换(尽管集合在运行时里面元素的"运行时类型"不变,即元素的getClass返回的还是最初

Java获取时间 时间计算 转换时间工具类

Java获取时间 时间计算 转换时间工具类 JAVA日期工具类 package com.mh.util; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 时间日期转换工具类 */ public class DateTimeUtil { /** *

java获取当前类的绝对路径

转自: http://blog.csdn.net/elina_1992/article/details/47419097 1.如何获得当前文件路径 常用: (1).Test.class.getResource("") 得到的是当前类FileTest.class文件的URI目录.不包括自己! (2).Test.class.getResource("/") 得到的是当前的classpath的绝对URI路径. (3).Thread.currentThread().getC