zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java获取指定包名下的所有类的全类名的解决方案详解编程语言

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);
 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方法的区别