项目需要,仅做记录。
支持包名下的子包名遍历,并使用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;/*** 用于获取指定包名下的所有类名.<br/>* 并可设置是否遍历该包名下的子包的类名.<br/>* 并可通过Annotation(内注)来过滤,避免一些内部类的干扰.<br/>* * @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的过滤项,即可只选出ClassTestDemolist = getClassList(pkg, recursive, author.class);for(int i = 0;i < list.size(); i ++){System.out.println(i +":"+list.get(i));}}public static List<Class<?>> getClassList(String pkgName , boolean isRecursive, Class<? extends Annotation> annotation) {List<Class<?>> classList = new ArrayList<Class<?>>();ClassLoader loader = Thread.currentThread().getContextClassLoader();try {// 按文件的形式去查找String strFile = pkgName.replaceAll("\\.", "/");Enumeration<URL> 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<Class<?>> 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类库的引用。<br/>* @throws IOException * */public static void findClassName(List<Class<?>> 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<JarEntry> jarEntries = jarFile.entries();while (jarEntries.hasMoreElements()) {JarEntry jarEntry = jarEntries.nextElement();String jarEntryName = jarEntry.getName(); // 类似:sun/security/internal/interfaces/TlsMasterSecret.classString 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() {@Overridepublic 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<Class<?>> 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] 遍历指定包名下所有的类(支持jar)相关推荐

  1. java 历遍 类_[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.util.concurrent 包下面的所有类

    java.util.concurrent 包下面的所有类 原子操作数类: java.util.concurrent.atomic.AtomicBoolean.class java.util.concu ...

  5. Java 遍历指定目录下的所有目录

    使用File类的list方法遍历指定目录下的所有目录 完整代码 import java.io.*;class Main {public static void main(String[] args) ...

  6. Java开发常用包、接口和类

    一.JDK中常用包 1.java.lang 这个是系统的基础类: 2.java.io 这里面是所有输入输出有关的类,比如文件操作等: 3.java.nio 为了完善 io 包中的功能,提高 io 包中 ...

  7. java反射获取包下所有的类

    引三方包 <dependency><groupId>org.reflections</groupId><artifactId>reflections&l ...

  8. java遍历易百教程_Java PrintStream类示例

    PrintStream类提供了将格式化数据写入基础输出流的附加功能.PrintStream打印的所有字符都使用平台的默认字符编码转换为字节. PrintStream类从不抛出IOException,它 ...

  9. java遍历易百教程_Java PushbackReader类示例

    PushbackReader是一个字符流读取器,允许将一个或多个字符推回到流中. 以下是PushbackReader类的示例.文件:PushbackReaderExample.java - packa ...

最新文章

  1. WPF Snoop 2.7 源码研究
  2. oracle共享时监听,Oracle监听---共享连接参数配置介绍
  3. python图片-python实现读取并显示图片的两种方法
  4. 页面中color颜色值_HTML+CSS 基础知识-入门概括-颜色与单位
  5. Vue.js——vue-resource全攻略
  6. 公用机房计算机主板选购,才知道,IDC机房运维工作居然可以如此简单!
  7. mybatis使用in语句作为查询条件
  8. SQL注入-联合注入
  9. 5198.丑数III
  10. maven 如何引入不同版本_React中不同webpack版本如何配置less
  11. [算法题] 安排会议室——贪心算法的应用
  12. android连接苹果蓝牙耳机,苹果蓝牙耳机怎么配对 苹果蓝牙耳机怎么配对安卓手机 苹果蓝牙耳机使用说明...
  13. 淘宝/天猫/京东/拼多多/苏宁易购/小米商城/华为商城/抖音快手直播/茅台抢购助手,宝惠抢购助手/OK助手源码
  14. Unity特效制作规范
  15. Mybatis如果存在该条数据则修改,否则新增
  16. Halcon:多张图片合并成一张图片
  17. 微信 html avi视频无法播放,是真的,微信可以发送高清.avi 了
  18. 机器学习 | 台大林轩田机器学习基石课程笔记12 --- Nonlinear Transformation
  19. docker:虚拟化和docker容器概念
  20. 算术左、右移位与逻辑左、右移位,右移一位和除二的区别、算术溢出

热门文章

  1. 2021年第十二届蓝桥杯省赛C/C++B组题解总结
  2. xmlHttp.send(null)与xmlHttp.send…
  3. Abase2:字节跳动新一代高可用 NoSQL 数据库
  4. DLL注入_远程线程注入
  5. vs编译运行报错:未声明的标识符
  6. Vue 实现可拖拽、拖拽组件
  7. PHP开发环境的搭建
  8. hide,hidden,display:none,visibility的区别
  9. mysql派生表(Derived Table)简单解析使用的小例子
  10. 利用Glide 对设备上的图片进行压缩并保存