Java 获取指定包名下的所有类的全类名的解决⽅案
最近有个需求需要获取⼀个指定包下的所有类的全类名,因此特意写了个获取指定包下所有类的全类名的⼯具类。在此记录⼀下,⽅便后续查阅
⼀、思路
通过ClassLoader 来查指定包,如果是在classes ⽂件夹下的class ⽂件,则⽤遍历⽂件的⽅式来获取该包下的所有类名。如果这个包名是jar 包⾥⾯的,那么需要通过遍历jar 包内⽂件的⽅式来获取该包下的所有类的类名
⼆、代码
代码如下 package  com .zxy.demomon.utils;import  java.io.File;import  java.io.IOException;import  java.JarURLConnection;import  java.URL;import  java.util.ArrayList;import  java.util.Enumeration;import  java.util.List;import  java.util.jar.JarEntry;import  java.util.jar.JarFile;/** * ClazzUtils  * @author ZENG.XIAO.YAN  * @version 1.0 */public  class  ClazzUtils  {    private  static  final  String CLASS_SUFFIX = ".class";    private  static  final  String CLASS_FILE_PREFIX = File.separator + "classes"  + File.separator;    private  static  final  String PACKAGE_SEPARATOR = ".";
                    /**    * 查包下的所有类的名字    * @param packageName      * @param showChildPackageFlag 是否需要显⽰⼦包内容    * @return List 集合,内容为类的全名    */    public  static  List<String> getClazzName(String packageName, boolean showChildPackageFlag ) {        List<String> result = new  ArrayList<>();        String suffixPath = placeAll("\\.", "/");        ClassLoader loader = Thread.currentThread().getContextClassLoader();        try  {            Enumeration<URL> urls = Resources(suffixPath);            while (urls.hasMoreElements()) {                URL url = Element();                if (url != null ) {                    String protocol = Protocol();                    if ("file".equals(protocol)) {                        String path = Path();
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));
1
2
3
4
5
6
7
8mysql下载jar包
9
10
11
1213
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42434445
46
47
48
49
50
51
52
53
}
}
}
}
} catch  (IOException e) {
e.printStackTrace();
}
return  result;
}
/**
* 递归获取所有class ⽂件的名字
* @param file
* @param flag  是否需要迭代遍历
* @return List
*/
private  static  List<String> getAllClassNameByFile(File file, boolean flag) {
List<String> result =  new  ArrayList<>();
if (!ists()) {
return  result;
}
if (file.isFile()) {
String path = Path();
// 注意:这⾥替换⽂件分割符要⽤replace 。因为replaceAll ⾥⾯的参数是正则表达式,⽽windows 环境中File.separator="\\"的,因此会有问题            if (dsWith(CLASS_SUFFIX)) {
path = place(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 : li
stFiles) {                    if (flag) {                        result.addAll(getAllClassNameByFile(f, flag));                    } else  {                        if (f.isFile()){                            String path = f.getPath();                            if (dsWith(CLASS_SUFFIX)) {                                path = place(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;
}
}
/**
* 递归获取jar 所有class ⽂件的名字
* @param jarFile
* @param packageName 包名
* @param flag  是否需要迭代遍历
* @return List
*/
54555657585960616263646566676869707172737475767778798081
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105106107108109110111112113114115116117118119120121122123
三、⼩结
(1)写代码时,注意String 类的replace ⽅法和replaceAll ⽅法的区别
(2)内部类⽣成的class ⽂件有有美元符号"$"    private  static  List<String> getAllClassNameByJar(JarFile jarFile, String packageName, boolean flag) {        List<String> result =  new  ArrayList<>();
Enumeration<JarEntry> entries = ies();
while (entries.hasMoreElements()) {
JarEntry jarEntry = Element();
String name = Name();
// 判断是不是class ⽂件
if (dsWith(CLASS_SUFFIX)) {
name = place(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 = ClazzName("sql.fabric", false );
for  (String string : list) {
System.out.println(string);
}
}
}
124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。