Java获取指定包名下的所有类的全类名的解决方案详解编程语言
2023-06-13 09:20:44 时间
最近有个需求需要获取一个指定包下的所有类的全类名,因此特意写了个获取指定包下所有类的全类名的工具类。在此记录一下,方便后续查阅
通过ClassLoader来查找指定包,如果是在classes文件夹下的class文件,则用遍历文件的方式来获取该包下的所有类名。如果这个包名是jar包里面的,那么需要通过遍历jar包内文件的方式来获取该包下的所有类的类名 代码如下
* @param showChildPackageFlag 是否需要显示子包内容 * @return List集合,内容为类的全名 public static List String getClazzName(String packageName, boolean showChildPackageFlag ) { List String result = new ArrayList (); String suffixPath = packageName.replaceAll("//.", "/"); ClassLoader loader = Thread.currentThread().getContextClassLoader(); try { Enumeration URL urls = loader.getResources(suffixPath); while(urls.hasMoreElements()) { URL url = urls.nextElement(); if(url != null) { String protocol = url.getProtocol(); if("file".equals(protocol)) { String path = url.getPath(); System.out.println(path); result.addAll(getAllClassNameByFile(new File(path), showChildPackageFlag)); } else if("jar".equals(protocol)) { JarFile jarFile = null; try{ jarFile = ((JarURLConnection) url.openConnection()).getJarFile(); } catch(Exception e){ e.printStackTrace(); if(jarFile != null) { result.addAll(getAllClassNameByJar(jarFile, packageName, showChildPackageFlag)); } catch (IOException e) { e.printStackTrace(); return result;
private static List String getAllClassNameByFile(File file, boolean flag) { List String result = new ArrayList (); if(!file.exists()) { return result; if(file.isFile()) { String path = file.getPath(); // 注意:这里替换文件分割符要用replace。因为replaceAll里面的参数是正则表达式,而windows环境中File.separator="//"的,因此会有问题 if(path.endsWith(CLASS_SUFFIX)) { path = path.replace(CLASS_SUFFIX, ""); // 从"/classes/"后面开始截取 String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length()) .replace(File.separator, PACKAGE_SEPARATOR); if(-1 == clazzName.indexOf("$")) { result.add(clazzName); return result; } else { File[] listFiles = file.listFiles(); if(listFiles != null listFiles.length 0) { for (File f : listFiles) { if(flag) { result.addAll(getAllClassNameByFile(f, flag)); } else { if(f.isFile()){ String path = f.getPath(); if(path.endsWith(CLASS_SUFFIX)) { path = path.replace(CLASS_SUFFIX, ""); // 从"/classes/"后面开始截取 String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length()) .replace(File.separator, PACKAGE_SEPARATOR); if(-1 == clazzName.indexOf("$")) { result.add(clazzName); return result;
private static List String getAllClassNameByJar(JarFile jarFile, String packageName, boolean flag) { List String result = new ArrayList (); Enumeration JarEntry entries = jarFile.entries(); while(entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String name = jarEntry.getName(); // 判断是不是class文件 if(name.endsWith(CLASS_SUFFIX)) { name = name.replace(CLASS_SUFFIX, "").replace("/", "."); if(flag) { // 如果要子包的文件,那么就只要开头相同且不是内部类就ok if(name.startsWith(packageName) -1 == name.indexOf("$")) { result.add(name); } else { // 如果不要子包的文件,那么就必须保证最后一个"."之前的字符串和包名一样且不是内部类 if(packageName.equals(name.substring(0, name.lastIndexOf("."))) -1 == name.indexOf("$")) { result.add(name); return result; public static void main(String[] args) { List String list = ClazzUtils.getClazzName("com.mysql.fabric", false); for (String string : list) { System.out.println(string);
(1)写代码时,注意String类的replace方法和replaceAll方法的区别
通过ClassLoader来查找指定包,如果是在classes文件夹下的class文件,则用遍历文件的方式来获取该包下的所有类名。如果这个包名是jar包里面的,那么需要通过遍历jar包内文件的方式来获取该包下的所有类的类名 代码如下
* @param showChildPackageFlag 是否需要显示子包内容 * @return List集合,内容为类的全名 public static List String getClazzName(String packageName, boolean showChildPackageFlag ) { List String result = new ArrayList (); String suffixPath = packageName.replaceAll("//.", "/"); ClassLoader loader = Thread.currentThread().getContextClassLoader(); try { Enumeration URL urls = loader.getResources(suffixPath); while(urls.hasMoreElements()) { URL url = urls.nextElement(); if(url != null) { String protocol = url.getProtocol(); if("file".equals(protocol)) { String path = url.getPath(); System.out.println(path); result.addAll(getAllClassNameByFile(new File(path), showChildPackageFlag)); } else if("jar".equals(protocol)) { JarFile jarFile = null; try{ jarFile = ((JarURLConnection) url.openConnection()).getJarFile(); } catch(Exception e){ e.printStackTrace(); if(jarFile != null) { result.addAll(getAllClassNameByJar(jarFile, packageName, showChildPackageFlag)); } catch (IOException e) { e.printStackTrace(); return result;
private static List String getAllClassNameByFile(File file, boolean flag) { List String result = new ArrayList (); if(!file.exists()) { return result; if(file.isFile()) { String path = file.getPath(); // 注意:这里替换文件分割符要用replace。因为replaceAll里面的参数是正则表达式,而windows环境中File.separator="//"的,因此会有问题 if(path.endsWith(CLASS_SUFFIX)) { path = path.replace(CLASS_SUFFIX, ""); // 从"/classes/"后面开始截取 String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length()) .replace(File.separator, PACKAGE_SEPARATOR); if(-1 == clazzName.indexOf("$")) { result.add(clazzName); return result; } else { File[] listFiles = file.listFiles(); if(listFiles != null listFiles.length 0) { for (File f : listFiles) { if(flag) { result.addAll(getAllClassNameByFile(f, flag)); } else { if(f.isFile()){ String path = f.getPath(); if(path.endsWith(CLASS_SUFFIX)) { path = path.replace(CLASS_SUFFIX, ""); // 从"/classes/"后面开始截取 String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length()) .replace(File.separator, PACKAGE_SEPARATOR); if(-1 == clazzName.indexOf("$")) { result.add(clazzName); return result;
private static List String getAllClassNameByJar(JarFile jarFile, String packageName, boolean flag) { List String result = new ArrayList (); Enumeration JarEntry entries = jarFile.entries(); while(entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String name = jarEntry.getName(); // 判断是不是class文件 if(name.endsWith(CLASS_SUFFIX)) { name = name.replace(CLASS_SUFFIX, "").replace("/", "."); if(flag) { // 如果要子包的文件,那么就只要开头相同且不是内部类就ok if(name.startsWith(packageName) -1 == name.indexOf("$")) { result.add(name); } else { // 如果不要子包的文件,那么就必须保证最后一个"."之前的字符串和包名一样且不是内部类 if(packageName.equals(name.substring(0, name.lastIndexOf("."))) -1 == name.indexOf("$")) { result.add(name); return result; public static void main(String[] args) { List String list = ClazzUtils.getClazzName("com.mysql.fabric", false); for (String string : list) { System.out.println(string);
private static final String CLASS_FILE_PREFIX = File.separator + "classes" + File.separator;
public static List String getClazzName(String packageName, boolean showChildPackageFlag ) {
result.addAll(getAllClassNameByFile(new File(path), showChildPackageFlag));
jarFile = ((JarURLConnection) url.openConnection()).getJarFile();
result.addAll(getAllClassNameByJar(jarFile, packageName, showChildPackageFlag));
private static List String getAllClassNameByFile(File file, boolean flag) {
// 注意:这里替换文件分割符要用replace。因为replaceAll里面的参数是正则表达式,而windows环境中File.separator="//"的,因此会有问题
String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length())
String clazzName = path.substring(path.indexOf(CLASS_FILE_PREFIX) + CLASS_FILE_PREFIX.length())
private static List String getAllClassNameByJar(JarFile jarFile, String packageName, boolean flag) {
// 如果不要子包的文件,那么就必须保证最后一个"."之前的字符串和包名一样且不是内部类
if(packageName.equals(name.substring(0, name.lastIndexOf("."))) -1 == name.indexOf("$")) {
(1)写代码时,注意String类的replace方法和replaceAll方法的区别
相关文章
- java怎么运行_怎样启动JAVA?「建议收藏」
- 在线学习Java的几个网站,别再盲目学习java了![通俗易懂]
- MySQL字段类型如何转为java_Java JDBC中,MySQL字段类型到JAVA类型的转换
- java无法获取服务器上路径,JAVA获取服务器路径的步骤
- java cloneable 用途_java中cloneable的使用「建议收藏」
- java数组 初始化_用Java初始化数组「建议收藏」
- java销毁定时器_Java 定时器退出解决方案
- java查找字符的方法_Java字符串查找(3种方法)
- java作用域-翻译:⚡⛓️可视化的 JavaScript作用域(链)
- Java Development Kit(JDK) 8 新特性(简述)详解手机开发
- Java Activiti6.0 spring5 SSM 工作流引擎 审批流程 java项目框架详解编程语言
- Java学习笔记之七java函数的语法规则总结详解编程语言
- Java学习笔记之六java三种循环(for,while,do……while)的使用方法及区别详解编程语言
- Java学习笔记之五java数组详解编程语言
- Java在Linux系统上的安装(java安装linux)
- Control character in cookie value, consider BASE64 encoding your value , java操作cookie遇到中文会报错的解决方案详解编程语言
- 服务器是否开机Java检查Linux服务器开机状态(java判断linux)
- Java与Redis结合:失效过期问题解决方案(redisjava过期)
- 让Java桥接Linux新世界的重要性(java链接linux)
- MySQL与Java的数据交互之旅(mysql对应java)
- 使用Java实现MySQL数据恢复操作(java恢复mysql)
- Java与MySQL共同构建良好的数据表(java mysql 表)
- 查找Java进程:Linux解决方案(linux查找java进程)