java 历遍 类_[Java] 遍历指定包名下所有的类(支持jar) | 学步园
项目需要,仅做记录。
支持包名下的子包名遍历,并使用Annotation(内注)来过滤一些不必要的内部类,提高命中精度。
通过Thread.currentThread().getContextClassLoader()获取ClassLoader实例
将包名转为路径名后,做为参数传给CloassLoader.getResources(),以得到该路径下所有资源的URL;
通过URL.getProtocol()方法,判断资源是在本地(file:)或是第三方jar包(jar:)内;
在本地的类直接文件遍历即可;
第三方jar则通过URL.openConnection()得到JarURLConnection,再通过JarURLConnection.getJarFile()获得JarFile,最后遍历该JarFile的item即可。
示例工程结构见下图.
package lab.sodino.clazz;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation:见http://blog.csdn.net/sodino/article/details/7987888
* */
@Target(ElementType.TYPE)//ElementType.TYPE用于标识类、接口(包括内注自身)、枚举
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface author {
//修饰符仅可为public, protected, private & static的组合
public static enum AppEnum {
Web, Client, Service, Undesignated
};
//public & abstract的组合或默认
AppEnum type() default AppEnum.Undesignated;
String name() default "unknown";
String webSite() default "N/A";
}
package lab.sodino.clazz;
/**
* @author Sodino E-mail:sodino@qq.com
* @version Time:2014年2月10日 下午9:06:55
*/
@author(name="sodino", webSite="sodino.com")
public class ClassTestDemo {
}
package lab.sodino.clazz;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 用于获取指定包名下的所有类名.
* 并可设置是否遍历该包名下的子包的类名.
* 并可通过Annotation(内注)来过滤,避免一些内部类的干扰.
*
* @author Sodino E-mail:sodino@qq.com
* @version Time:2014年2月10日 下午3:55:59
*/
public class ClassUtil {
public static void main(String []args){
// 标识是否要遍历该包路径下子包的类名
//boolean recursive = false;
boolean recursive = true;
// 指定的包名
//String pkg = "javax.crypto.spec";// 为java/jre6/lib/jce.jar,普通的java工程默认已引用
//String pkg = "javax.crypto";
//String pkg = "lab.sodino";
String pkg = "lab.sodino.clazz";
List list = null;
//list = getClassList(pkg, recursive, null);
// 增加 author.class的过滤项,即可只选出ClassTestDemo
list = getClassList(pkg, recursive, author.class);
for(int i = 0;i < list.size(); i ++){
System.out.println(i +":"+list.get(i));
}
}
public static List> getClassList(String pkgName , boolean isRecursive, Class extends Annotation> annotation) {
List> classList = new ArrayList>();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
// 按文件的形式去查找
String strFile = pkgName.replaceAll("\\.", "/");
Enumeration urls = loader.getResources(strFile);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
String pkgPath = url.getPath();
System.out.println("protocol:" + protocol +" path:" + pkgPath);
if ("file".equals(protocol)) {
// 本地自己可见的代码
findClassName(classList, pkgName, pkgPath, isRecursive, annotation);
} else if ("jar".equals(protocol)) {
// 引用第三方jar的代码
findClassName(classList, pkgName, url, isRecursive, annotation);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classList;
}
public static void findClassName(List> clazzList, String pkgName, String pkgPath, boolean isRecursive, Class extends Annotation> annotation) {
if(clazzList == null){
return;
}
File[] files = filterClassFiles(pkgPath);// 过滤出.class文件及文件夹
System.out.println("files:" +((files == null)?"null" : "length=" + files.length));
if(files != null){
for (File f : files) {
String fileName = f.getName();
if (f.isFile()) {
// .class 文件的情况
String clazzName = getClassName(pkgName, fileName);
addClassName(clazzList, clazzName, annotation);
} else {
// 文件夹的情况
if(isRecursive){
// 需要继续查找该文件夹/包名下的类
String subPkgName = pkgName +"."+ fileName;
String subPkgPath = pkgPath +"/"+ fileName;
findClassName(clazzList, subPkgName, subPkgPath, true, annotation);
}
}
}
}
}
/**
* 第三方Jar类库的引用。
* @throws IOException
* */
public static void findClassName(List> clazzList, String pkgName, URL url, boolean isRecursive, Class extends Annotation> annotation) throws IOException {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
System.out.println("jarFile:" + jarFile.getName());
Enumeration jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName(); // 类似:sun/security/internal/interfaces/TlsMasterSecret.class
String clazzName = jarEntryName.replace("/", ".");
int endIndex = clazzName.lastIndexOf(".");
String prefix = null;
if (endIndex > 0) {
String prefix_name = clazzName.substring(0, endIndex);
endIndex = prefix_name.lastIndexOf(".");
if(endIndex > 0){
prefix = prefix_name.substring(0, endIndex);
}
}
if (prefix != null && jarEntryName.endsWith(".class")) {
//System.out.println("prefix:" + prefix +" pkgName:" + pkgName);
if(prefix.equals(pkgName)){
System.out.println("jar entryName:" + jarEntryName);
addClassName(clazzList, clazzName, annotation);
} else if(isRecursive && prefix.startsWith(pkgName)){
// 遍历子包名:子类
System.out.println("jar entryName:" + jarEntryName +" isRecursive:" + isRecursive);
addClassName(clazzList, clazzName, annotation);
}
}
}
}
private static File[] filterClassFiles(String pkgPath) {
if(pkgPath == null){
return null;
}
// 接收 .class 文件 或 类文件夹
return new File(pkgPath).listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
}
private static String getClassName(String pkgName, String fileName) {
int endIndex = fileName.lastIndexOf(".");
String clazz = null;
if (endIndex >= 0) {
clazz = fileName.substring(0, endIndex);
}
String clazzName = null;
if (clazz != null) {
clazzName = pkgName + "." + clazz;
}
return clazzName;
}
private static void addClassName(List> clazzList, String clazzName, Class extends Annotation> annotation) {
if (clazzList != null && clazzName != null) {
Class> clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//System.out.println("isAnnotation=" + clazz.isAnnotation() +" author:" + clazz.isAnnotationPresent(author.class));
if (clazz != null) {
if(annotation == null){
clazzList.add(clazz);
System.out.println("add:" + clazz);
} else if (clazz.isAnnotationPresent(annotation)){
clazzList.add(clazz);
System.out.println("add annotation:" + clazz);
}
}
}
}
}
java 历遍 类_[Java] 遍历指定包名下所有的类(支持jar) | 学步园相关推荐
- [Java] 遍历指定包名下所有的类(支持jar)
项目需要,仅做记录. 支持包名下的子包名遍历,并使用Annotation(内注)来过滤一些不必要的内部类,提高命中精度. 通过Thread.currentThread().getContextClas ...
- 获取指定包名下的所有类
写了一个工具类,用于获取指定包名下的所有类,支持递归遍历,支持注解过滤,可从 classpath (class 文件与 jar 包)中获取. import java.io.File; import j ...
- java 获取包名类名_获取指定包名下的所有类的类名(全名)
参考来源: 以下代码一键运行: package test; import java.io.File; import java.io.IOException; import java.net.JarUR ...
- Java解决递归栈溢出_方法递归调用中java栈溢出的问题 及 解答 | 学步园
为什么运行如下程序 , 方法sum2 不会导致栈溢出, 方法sum 会导致栈溢出? --------output----------- 32004000 java.lang.StackOverflow ...
- java中的原子操作_[Java并发系列] 2.Java中的原子操作类
1. 原子操作类的作用 当程序更新一个变量时,如果多个线程同时更新该变量,可能会得到期望以外的值.比如i=1, 线程A更新i+1, 同时线程B更新I+1,经过两个线程的操作,最终变量i的值可能不是3, ...
- java tar压缩工具类_分享apache的commons-compress的TarUtils压缩工具类对文件数据进行加解密、解析及格式化校验等操作...
一.前言 基于apache的commons-compress包中的org.apache.commons.compress.archivers.tar.TarUtils打包工具类对文件进行加解密.并对加 ...
- java教师薪资系统_“java实验代码即UML类图”之“教师工资发放”
实验二 2. 编写程序,实现计信学院学期末教师的奖金发放.教师有属性:编号.姓名,教学总工作量,奖金:其中奖金的计算方法为: x*30 (当职称为教授时) y= x*25 (当职称为副教授时) x*2 ...
- java 基础面试 英文_[Java面试] 面试java基础总结大全
原标题:[Java面试] 面试java基础总结大全 基础知识: 1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. ...
- java输入输出及文件_(java基础)Java输入输出流及文件相关
字节流: 所有的字节输入输出都继承自InputStream和OutputStream,通常用于读取二进制数据,最基本单位为单个字节,如图像和声音.默认不使用缓冲区. FileInputStream和F ...
最新文章
- 一位数据科学家的私房工具清单
- ES10 可以使用几个新特性
- 为什么CRM WebClient UI每次点了回车都会触发到后台的roundtrip
- Apache Camel 3 –骆驼核心vs骆驼核心引擎(较小的核心)
- 第十二单元 打包,压缩,主机传送文件
- PCB设计--PCB画图技巧
- 在ECSHOP后台左侧导航中增加新菜单
- 安装篇——新建一个VUE项目
- 2020-09-10 保证软件开发过程遵循ISO 26262标准的十个主要进阶步骤
- SAP-MM知识精解-批次管理(01)- 概览及物料的批次启用
- 修正Linux下WPS字体库缺失
- 海康NVR录像机集成大华摄像头
- halcon 条形码识别(持续更新)
- win10 计算机 搜索文件,如何在win10搜索指定文件_教你在win10搜索指定文件的方法...
- Scheme 语言概要上
- 万物皆可GAN之pytorch和神经网络
- 读《南怀瑾讲人生哲理》
- linux环境vmd安装,Ubuntu下VMD安装
- ffmpeg在低版本VS中的编译
- PostgreSQL不等于判断
热门文章
- uni-app z-index无效的解决办法(遮罩层)
- [ACL2017]Going out on a limb:Joint Extraction of Entity Mentions and Relations without Depende...
- macbook android 屏幕共享,苹果设备小技巧:iPhone,iPad,Mac进行屏幕共享和远程控制...
- 适合后台管理系统开发的前端框架
- 35+老测试员生涯回顾,揭秘无力吐槽的自动化真相…
- StrStrI 与 strstr
- 4.Executor执行器
- chrome插件莫名消失【已解决】
- 肝了1个月!2022 顶会论文代码大合集!
- C++STL accumulate函数