在JAVA中,获取一个类的全部父类是比较简单的,只需要通过反射(Class的getSuperclass()方法)即可。然而,如果想获得一个类的所有子类,或者获得实现某一个接口的所有实现类,相对比较麻烦。

用过Eclipse的开发人员都知道,通过F4键或(Ctrl+T组合键)可以查到指定类的类层次结构。仔细想一下该快捷键的实现原理,或许可以找到一个可行的设计思路。

首先,需要确定一个前提是,寻找所有子类,必须先指定搜索的文件范围。打个比方,要寻找一个古人的所有后代成员,必须设置查找的地理范围是在中国内,否则就无从入手。

结合实际的项目部署环境,查找子类的方法需要有两种方式。第一种,在开发环境,可以直接遍历指定范围下的所有源代码文件,再结合反射的知识;第二种,假设项目已经打成jar包,则只能通过jar包获得所有类文件。

下面给出具体的代码实现

1.若是开发环境,则通过递归查找指定目录下的类文件的全路径,代码如下

 /**
* 递归查找指定目录下的类文件的全路径
*
* @param baseFile 查找文件的入口
* @param fileList 保存已经查找到的文件集合
*/
public static void getSubFileNameList(File baseFile, List<String> fileList) {
if (baseFile.isDirectory()) {
File[] files = baseFile.listFiles();
for (File tmpFile : files) {
getSubFileNameList(tmpFile, fileList);
}
}
String path = baseFile.getPath();
if (path.endsWith(".java")) {
String name1 = path.substring(path.indexOf("src") + 4, path.length());
String name2 = name1.replaceAll("\\\\", ".");
String name3 = name2.substring(0, name2.lastIndexOf(".java"));
fileList.add(name3);
}
}

获取根路径方法 final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());

2.若是jar包环境,则可以通过JarFile这个工具类,获得所有全部类信息

 /**
* 从jar包读取所有的class文件名
*/
private static List<String> getClassNameFrom(String jarName) {
List<String> fileList = new ArrayList<String>();
try {
JarFile jarFile = new JarFile(new File(jarName));
Enumeration<JarEntry> en = jarFile.entries(); // 枚举获得JAR文件内的实体,即相对路径
while (en.hasMoreElements()) {
String name1 = en.nextElement().getName();
if (!name1.endsWith(".class")) {//不是class文件
continue;
}
String name2 = name1.substring(0, name1.lastIndexOf(".class"));
String name3 = name2.replaceAll("/", ".");
fileList.add(name3);
}
} catch (IOException e) {
e.printStackTrace();
} return fileList;
}

3.从前两步可以得到所有子类或所有接口实现类的类路径信息,有了类的全路径,就可以通过反射拿到类的信息,用来判断是否满足条件

 /**
* 判断一个类是否继承某个父类或实现某个接口
*/
public static boolean isChildClass(String className, Class parentClazz) {
if (className == null) return false; Class clazz = null;
try {
clazz = Class.forName(className);
if (Modifier.isAbstract(clazz.getModifiers())) {//抽象类忽略
return false;
}
if (Modifier.isInterface(clazz.getModifiers())) {//接口忽略
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return parentClazz.isAssignableFrom(clazz); }

4.写几个简单的测试类,用来说明问题

 package bean;

 public abstract class Animal {
public abstract void eat();
public abstract void walk();
}
 package bean;

 public class Cat extends Animal{

     @Override
public void eat() {
System.err.println("小猫吃东西");
} @Override
public void walk() {
System.err.println("小猫走路");
} }
 package bean;

 public class Dog extends Animal{

     @Override
public void eat() {
System.err.println("小狗吃东西");
} @Override
public void walk() {
System.err.println("小狗走路");
} }
 package bean;

 public class Person {
private String name;
private int age; public Person(){ }
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
} public void sayHello(){
System.err.println("hello,i am " + this.name);
}
}

5.入口方法,打印输出结果(jar包可直接使用Eclipse导出可执行jar文件)

     List<String> fileList = new ArrayList<String>();

     File baseFile = new File(getSrcPath() + File.separator + "src" + File.separator + "bean");
if(baseFile.exists()){//开发环境,读取源文件
getSubFileNameList(baseFile,fileList);
}else{//jar包环境
fileList=getClassNameFrom("server.jar");
}
System.err.println("Animal类的所有子类有");
for(String name:fileList){
if(isChildClass(name,Animal.class))
System.err.println(name);
}

java获取全部子类或接口的全部实现的更多相关文章

  1. Java 获取所有子类信息

    我以前的博客(Java Scala获取注解的类信息)介绍过通过Reflections工具通过使用特定注解的类的信息,其实本工具也可以获取接口,抽象类,类等的所有子类信息.使用方法如下: Reflect ...

  2. java获取https网站证书,附带调用https:webservice接口

    一.java 获取https网站证书: 1.创建一个java工程,新建InstallCert类,将以下代码复制进去 package com; import java.io.BufferedReader ...

  3. Java开发知识之Java中的集合Set接口以及子类应用

    ---恢复内容开始--- Java开发知识之Java中的集合Set接口以及子类应用 一丶Set接口以及作用 在上一讲.我们熟悉了接口的实现图.以及自己各有的子类. List接口主要存储的数据是可以重复 ...

  4. Java多线程和并发(四),线程返回值获取方式和Callable接口

    目录 1.主线程等待法 2.使用Thread类的join()阻塞当前线程,等待子线程执行完毕 3.通过Callable接口实现:通过FutureTask Or线程池获取 四.线程返回值获取方式和Cal ...

  5. Java集合框架之Collection接口

    Java是一门面向对象的语言,那么我们写程序的时候最经常操作的便是对象了,为此,Java提供了一些专门用来处理对象的类库,这些类库的集合我们称之为集合框架.Java集合工具包位于Java.util包下 ...

  6. 黑马程序员——JAVA基础之抽象和接口 , 模版方法设计模式

    ------- android培训.java培训.期待与您交流! ---------- 抽象定义:           抽象就是从多个事物中将共性的,本质的内容抽取出来.           例如:狼 ...

  7. Java 继承、抽象、接口

    一.继承 1. 概述 继承是面向对象的重要特征之一,当多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那多个类中无需再定义这些属性和行为,只需继承那个单独的类即可. 单独的类称为父类或超 ...

  8. java获取泛型信息

    总结一下java中获取与泛型相关的信息的知识,不如说是使用方法.网上也有很多类似的优秀文章,这里主要做一个知识的总结.通过反射获取泛型信息的常见例子: //bean package testProje ...

  9. java 集合框架(二)Iterable接口

    Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...

随机推荐

  1. 模拟赛20181031 雅礼 Wearry 养花 折射 画作

    % Day1 Solution % Wearry % Stay determined! 养花    考虑当 kkk 确定的时候如何求答案, 显然对于所有形如 [ak,(a+1)k)[ak, (a+1) ...

  2. kafka数据组织+集群架构

    1.数据组织: partition:Kafka的topic可以划分成一个或多个partition,每个partition存储着这个topic的一部分数据. partition副本:若一个topic的副 ...

  3. HTML5自定义属性操作

    一.自定义属性(html5标准)data-属性名称="属性值" 自定义属性的名称驼峰式命名规则需要用-隔开 自定义属性名称如果连在一起写,大写会自动转为小写 data-user=& ...

  4. Problem 4 dp

    $des$ 小 $Y$ 十分喜爱光学相关的问题, 一天他正在研究折射.他在平面上放置了 $n$ 个折射装置, 希望利用这些装置画出美丽的折线.折线将从某个装置出发, 并且在经过一处装置时可以转向, 若 ...

  5. 洛谷 P1456Monkey King

    题目描述 要把打架的两堆猴子合并为一堆,查询的又是最大值,所以很容易想到可并堆. 题目要求打完架后战斗力最大的猴子的战斗力要减半,但不能直接在堆中进行这个操作,因为战斗力减半后这只猴子不一定是战斗力最 ...

  6. codecs 1264 芳香数

    1264 芳香数 题目描述 Description This question involves calculating the value of aromatic numbers which are ...

  7. secureCRT连接服务器和文件传输( 一步搞定)

    1.在百度云盘存有此工具,获取到后解压执行即可,如下2 连接目标服务器 192.xxx.xx.xx 2.secureCRT连接服务器和文件传输 ,现象如下 登录后切换到root用户即可有权限操作    ...

  8. ICEM-蜗壳

    原视频下载地址:https://yunpan.cn/cY8XxpyLN4QaE  访问密码 a792

  9. SpringBoot集成mybatis,同时读取一个数据库中多个数据表

    SpringBoot集成mybatis,同时读取一个数据库中多个数据表: application.properties: mybatis.config-location=classpath:mybat ...

  10. 深入理解JVM虚拟机10:JVM常用参数以及调优实践

    转自http://www.rowkey.me/blog/2016/11/02/java-profile/?hmsr=toutiao.io&utm_medium=toutiao.io&u ...