Java获取package下所有的class对象(普通文件包和Jar文件包)
程序员文章站
2022-05-20 18:37:15
...
读取一个package路径下面所有的class。
起初觉得很简单,只需要通过IO流找到文件,然后取出下面的所有文件,然后通过反射得到Class对象。
但是发现从普通文件包下面这样做很容易,但是要是package在一个jar文件的下,这就比价麻烦了,因为我们不能通过文件对象File那样直接定位到jar文件下面的内容。所以我们需要使用特殊的方式。
第一种:普通文件安包中的package里面
/** * 获得包下面的所有的class * * @param pack * package完整名称 * @return List包含所有class的实例 */ public static List<Class> getClasssFromPackage(String pack) { List<Class> clazzs = new ArrayList<Class>(); // 是否循环搜索子包 boolean recursive = true; // 包名字 String packageName = pack; // 包名对应的路径名称 String packageDirName = packageName.replace('.', '/'); Enumeration<URL> dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); while (dirs.hasMoreElements()) { URL url = dirs.nextElement(); String protocol = url.getProtocol(); if ("file".equals(protocol)) { System.out.println("file类型的扫描"); String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); findClassInPackageByFile(packageName, filePath, recursive, clazzs); } else if ("jar".equals(protocol)) { System.out.println("jar类型的扫描"); } } } catch (Exception e) { e.printStackTrace(); } return clazzs; } /** * 在package对应的路径下找到所有的class * * @param packageName * package名称 * @param filePath * package对应的路径 * @param recursive * 是否查找子package * @param clazzs * 找到class以后存放的集合 */ public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive, List<Class> clazzs) { File dir = new File(filePath); if (!dir.exists() || !dir.isDirectory()) { return; } // 在给定的目录下找到所有的文件,并且进行条件过滤 File[] dirFiles = dir.listFiles(new FileFilter() { @Override public boolean accept(File file) { boolean acceptDir = recursive && file.isDirectory();// 接受dir目录 boolean acceptClass = file.getName().endsWith("class");// 接受class文件 return acceptDir || acceptClass; } }); for (File file : dirFiles) { if (file.isDirectory()) { findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs); } else { String className = file.getName().substring(0, file.getName().length() - 6); try { clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className)); } catch (Exception e) { e.printStackTrace(); } } } }
第二种:获取jar文件包中的package下面的所有class
/** * 从jar文件中读取指定目录下面的所有的class文件 * * @param jarPaht * jar文件存放的位置 * @param filePaht * 指定的文件目录 * @return 所有的的class的对象 */ public List<Class> getClasssFromJarFile(String jarPaht, String filePaht) { List<Class> clazzs = new ArrayList<Class>(); JarFile jarFile = null; try { jarFile = new JarFile(jarPaht); } catch (IOException e1) { e1.printStackTrace(); } List<JarEntry> jarEntryList = new ArrayList<JarEntry>(); Enumeration<JarEntry> ee = jarFile.entries(); while (ee.hasMoreElements()) { JarEntry entry = (JarEntry) ee.nextElement(); // 过滤我们出满足我们需求的东西 if (entry.getName().startsWith(filePaht) && entry.getName().endsWith(".class")) { jarEntryList.add(entry); } } for (JarEntry entry : jarEntryList) { String className = entry.getName().replace('/', '.'); className = className.substring(0, className.length() - 6); try { clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return clazzs;
此外,我们可以通过JarEntry对象,将jar文件中的一个文件以流的方式输出来
/** * 通过流将jar中的一个文件的内容输出 * * @param jarPaht * jar文件存放的位置 * @param filePaht * 指定的文件目录 */ public static void getStream(String jarPaht, String filePaht) { JarFile jarFile = null; try { jarFile = new JarFile(jarPaht); } catch (IOException e1) { e1.printStackTrace(); } Enumeration<JarEntry> ee = jarFile.entries(); List<JarEntry> jarEntryList = new ArrayList<JarEntry>(); while (ee.hasMoreElements()) { JarEntry entry = (JarEntry) ee.nextElement(); // 过滤我们出满足我们需求的东西,这里的fileName是指向一个具体的文件的对象的完整包路径,比如com/mypackage/test.txt if (entry.getName().startsWith(filePaht)) { jarEntryList.add(entry); } } try { InputStream in = jarFile.getInputStream(jarEntryList.get(0)); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String s = ""; while ((s = br.readLine()) != null) { System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } }
测试上面的所有内容
public static void main(String[] args) { ClassUtil classUtil = new ClassUtil(); List<Class> clazzs = classUtil.getClasssFromPackage("包名");// for (Class clazz : clazzs) { System.out.println(clazz.getName()); } clazzs = classUtil.getClasssFromJarFile("Jar文件的路径", "Jar文件里面的包路径"); for (Class clazz : clazzs) { System.out.println(clazz.getName()); } classUtil.getStream("Jar文件的路径", "Jar文件总的一个具体文件的路径"); }