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 }
以上是 java获取全部子类或接口的全部实现 的全部内容, 来源链接: utcz.com/z/390913.html