zoukankan      html  css  js  c++  java
  • 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         }
  • 相关阅读:
    软件体系架构复习要点
    Operating System on Raspberry Pi 3b
    2019-2020 ICPC North-Western Russia Regional Contest
    2019 ICPC ShenYang Regional Online Contest
    2019 ICPC XuZhou Regional Online Contest
    2019 ICPC NanChang Regional Online Contest
    2019 ICPC NanJing Regional Online Contest
    Codeforces Edu Round 72 (Rated for Div. 2)
    Codeforces Round #583 (Div.1+Div.2)
    AtCoder Beginning Contest 139
  • 原文地址:https://www.cnblogs.com/linkenpark/p/11383355.html
Copyright © 2011-2022 走看看