项目需要,仅做记录。

支持包名下的子包名遍历,并使用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) | 学步园相关推荐

  1. [Java] 遍历指定包名下所有的类(支持jar)

    项目需要,仅做记录. 支持包名下的子包名遍历,并使用Annotation(内注)来过滤一些不必要的内部类,提高命中精度. 通过Thread.currentThread().getContextClas ...

  2. 获取指定包名下的所有类

    写了一个工具类,用于获取指定包名下的所有类,支持递归遍历,支持注解过滤,可从 classpath (class 文件与 jar 包)中获取. import java.io.File; import j ...

  3. java 获取包名类名_获取指定包名下的所有类的类名(全名)

    参考来源: 以下代码一键运行: package test; import java.io.File; import java.io.IOException; import java.net.JarUR ...

  4. Java解决递归栈溢出_方法递归调用中java栈溢出的问题 及 解答 | 学步园

    为什么运行如下程序 , 方法sum2 不会导致栈溢出, 方法sum 会导致栈溢出? --------output----------- 32004000 java.lang.StackOverflow ...

  5. java中的原子操作_[Java并发系列] 2.Java中的原子操作类

    1. 原子操作类的作用 当程序更新一个变量时,如果多个线程同时更新该变量,可能会得到期望以外的值.比如i=1, 线程A更新i+1, 同时线程B更新I+1,经过两个线程的操作,最终变量i的值可能不是3, ...

  6. java tar压缩工具类_分享apache的commons-compress的TarUtils压缩工具类对文件数据进行加解密、解析及格式化校验等操作...

    一.前言 基于apache的commons-compress包中的org.apache.commons.compress.archivers.tar.TarUtils打包工具类对文件进行加解密.并对加 ...

  7. java教师薪资系统_“java实验代码即UML类图”之“教师工资发放”

    实验二 2. 编写程序,实现计信学院学期末教师的奖金发放.教师有属性:编号.姓名,教学总工作量,奖金:其中奖金的计算方法为: x*30 (当职称为教授时) y= x*25 (当职称为副教授时) x*2 ...

  8. java 基础面试 英文_[Java面试] 面试java基础总结大全

    原标题:[Java面试] 面试java基础总结大全 基础知识: 1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. ...

  9. java输入输出及文件_(java基础)Java输入输出流及文件相关

    字节流: 所有的字节输入输出都继承自InputStream和OutputStream,通常用于读取二进制数据,最基本单位为单个字节,如图像和声音.默认不使用缓冲区. FileInputStream和F ...

最新文章

  1. 一位数据科学家的私房工具清单
  2. ES10 可以使用几个新特性
  3. 为什么CRM WebClient UI每次点了回车都会触发到后台的roundtrip
  4. Apache Camel 3 –骆驼核心vs骆驼核心引擎(较小的核心)
  5. 第十二单元       打包,压缩,主机传送文件
  6. PCB设计--PCB画图技巧
  7. 在ECSHOP后台左侧导航中增加新菜单
  8. 安装篇——新建一个VUE项目
  9. 2020-09-10 保证软件开发过程遵循ISO 26262标准的十个主要进阶步骤
  10. SAP-MM知识精解-批次管理(01)- 概览及物料的批次启用
  11. 修正Linux下WPS字体库缺失
  12. 海康NVR录像机集成大华摄像头
  13. halcon 条形码识别(持续更新)
  14. win10 计算机 搜索文件,如何在win10搜索指定文件_教你在win10搜索指定文件的方法...
  15. Scheme 语言概要上
  16. 万物皆可GAN之pytorch和神经网络
  17. 读《南怀瑾讲人生哲理》
  18. linux环境vmd安装,Ubuntu下VMD安装
  19. ffmpeg在低版本VS中的编译
  20. PostgreSQL不等于判断

热门文章

  1. uni-app z-index无效的解决办法(遮罩层)
  2. [ACL2017]Going out on a limb:Joint Extraction of Entity Mentions and Relations without Depende...
  3. macbook android 屏幕共享,苹果设备小技巧:iPhone,iPad,Mac进行屏幕共享和远程控制...
  4. 适合后台管理系统开发的前端框架
  5. 35+老测试员生涯回顾,揭秘无力吐槽的自动化真相…
  6. StrStrI 与 strstr
  7. 4.Executor执行器
  8. chrome插件莫名消失【已解决】
  9. 肝了1个月!2022 顶会论文代码大合集!
  10. C++STL accumulate函数