如何反射一个包下的所有类到一个List<Class<?>>

知擎物联 常州知擎物联科技有限公司 2014-02-25 10:47:43
加精
如何反射一个包下的所有类到一个List<Class<?>>
比如有一个包
package com.Models;

包下有以下类
public class ClientUser
public class ClientGroup
public class ClientRole

我想通过反射,获取到一个List<Class<?>>
其中包含了ClientUser,ClientGroup,ClientRole
...全文
20746 点赞 收藏 35
写回复
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
daker_129 2016-01-21
哎呦 不错哦,改一下路径可以用!
回复
zxj172266587 2016-01-20
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ScanPackage { /** *遍历包 并遍历子包 */ public static void scan(String packageName ,List<Class<?>> list) throws Exception{ String path=getSrcPath()+packageToDir(packageName); File dir=new File(path); File[] files=dir.listFiles(); Class<?> cla=null; for(File f:files){ if(f.isDirectory()){ String childName=packageName+"."+f.getName(); scan(childName, list); }else{ cla=Class.forName(packageName+"."+f.getName().split("\\.")[0]); list.add(cla); } } } /** 获取当前路径 */ public static String getSrcPath() throws IOException{ File file=new File(""); String path=file.getCanonicalPath()+File.separator+"src"; return path; } /** *package转换为路径格式 */ public static String packageToDir(String packageName){ String[] array=packageName.split("\\."); StringBuffer sb=new StringBuffer(); for(String str:array){ sb.append(File.separator).append(str); } return sb.toString(); } public static void main(String[] args) throws Exception { List<Class<?>> list=new ArrayList<Class<?>>(); scan("com.xx.xxx.xxxx",list);//把这个对象的路径写入,就可以了。 System.out.println(list.size()); for(Class<?> cla:list){ System.out.println(cla.getName()); } } } scan("com.xx.xxx.xxxx",list);//把这个对象的路径写入,就可以了。你可以debug一下,就可以,很好出来的。
回复
ceekay_ 2015-09-23
楼主你解决没,把解决方法贴出来啊
回复
放纵的青春 2015-08-03
http://guoliangqi.iteye.com/blog/644876 拿去改改就能用了
回复
tryrtytytyt 2015-07-14
android怎么根据包名获取文件夹路径啊,求教
回复
猿小鹏 2015-03-10
楼主应该可以用递归处理了
回复
kosora曹 2015-03-03
引用 26 楼 wzr208 的回复:
[quote=引用 19 楼 SmallYamateh 的回复:] 这没什么难的吧,就一个先序遍历:


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ScanPackage {
/**
 *遍历包  并遍历子包
 */
public static void scan(String packageName ,List<Class<?>> list) throws Exception{
    String path=getSrcPath()+packageToDir(packageName);
    File dir=new File(path);
    File[] files=dir.listFiles();
    Class<?> cla=null;
    for(File f:files){
        if(f.isDirectory()){
            String childName=packageName+"."+f.getName();
            scan(childName, list);

        }else{
            cla=Class.forName(packageName+"."+f.getName().split("\\.")[0]);
            list.add(cla);
        }
    }
}
/**
获取当前路径
*/
public static String getSrcPath() throws IOException{
   File file=new File("");
   String path=file.getCanonicalPath()+File.separator+"src";
   return path;
}
/**
 *package转换为路径格式
 */
public static String packageToDir(String packageName){
    String[] array=packageName.split("\\.");
    StringBuffer sb=new StringBuffer();
    for(String str:array){
        sb.append(File.separator).append(str);
    }
    return sb.toString();
}
public static void main(String[] args) throws Exception {
    List<Class<?>> list=new ArrayList<Class<?>>();
   scan("com.Models",list);
   System.out.println(list.size());
    for(Class<?> cla:list){
        System.out.println(cla.getName());
    }
}
}

我想知道 spring中自动扫描包下所有带注解的类是怎么做到的啊[/quote] 既然文件路径有了,比如com/isoft/dao/UserDao.java,那么就有com.iosft.dao.UserDao.java,然后就能用Class.forName()取得Class,接着用getAnnotations()取得注解数组,看看里边是否有@Component,如果有的话,就添加到上下文当中
回复
u012569996 2015-03-03
引用 8 楼 huxiweng 的回复:
思路: 通过包名得到文件夹路劲。 通过File类列出所有文件。再根据包名+文件名进行反射
这个可以有哦,正解。
回复
铁匠梁 2015-02-25
自己解析遍历jar文件,取得包名+classname,然后反射取得想要的属性。
回复
wzr208 2015-02-25
引用 19 楼 SmallYamateh 的回复:
这没什么难的吧,就一个先序遍历:


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ScanPackage {
/**
 *遍历包  并遍历子包
 */
public static void scan(String packageName ,List<Class<?>> list) throws Exception{
    String path=getSrcPath()+packageToDir(packageName);
    File dir=new File(path);
    File[] files=dir.listFiles();
    Class<?> cla=null;
    for(File f:files){
        if(f.isDirectory()){
            String childName=packageName+"."+f.getName();
            scan(childName, list);

        }else{
            cla=Class.forName(packageName+"."+f.getName().split("\\.")[0]);
            list.add(cla);
        }
    }
}
/**
获取当前路径
*/
public static String getSrcPath() throws IOException{
   File file=new File("");
   String path=file.getCanonicalPath()+File.separator+"src";
   return path;
}
/**
 *package转换为路径格式
 */
public static String packageToDir(String packageName){
    String[] array=packageName.split("\\.");
    StringBuffer sb=new StringBuffer();
    for(String str:array){
        sb.append(File.separator).append(str);
    }
    return sb.toString();
}
public static void main(String[] args) throws Exception {
    List<Class<?>> list=new ArrayList<Class<?>>();
   scan("com.Models",list);
   System.out.println(list.size());
    for(Class<?> cla:list){
        System.out.println(cla.getName());
    }
}
}

我想知道 spring中自动扫描包下所有带注解的类是怎么做到的啊
回复
DechaoMeng 2014-03-02
终于知道怎么找到包里的类名了,谢谢大神们
回复
围观遍历java下所有的类的方法
回复
kosora曹 2014-02-26
那应该就是31行的函数的问题:

String path=file.getCanonicalPath()+File.separator+"src";
这个函数在Eclipse中是正确的,可能不支持android系统;你找找android中有没有类似于"获取当前路径"之类的函数。
回复
知擎物联 2014-02-26
引用 19 楼 SmallYamateh 的回复:
这没什么难的吧,就一个先序遍历:


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ScanPackage {
/**
 *遍历包  并遍历子包
 */
public static void scan(String packageName ,List<Class<?>> list) throws Exception{
    String path=getSrcPath()+packageToDir(packageName);
    File dir=new File(path);
    File[] files=dir.listFiles();
    Class<?> cla=null;
    for(File f:files){
        if(f.isDirectory()){
            String childName=packageName+"."+f.getName();
            scan(childName, list);

        }else{
            cla=Class.forName(packageName+"."+f.getName().split("\\.")[0]);
            list.add(cla);
        }
    }
}
/**
获取当前路径
*/
public static String getSrcPath() throws IOException{
   File file=new File("");
   String path=file.getCanonicalPath()+File.separator+"src";
   return path;
}
/**
 *package转换为路径格式
 */
public static String packageToDir(String packageName){
    String[] array=packageName.split("\\.");
    StringBuffer sb=new StringBuffer();
    for(String str:array){
        sb.append(File.separator).append(str);
    }
    return sb.toString();
}
public static void main(String[] args) throws Exception {
    List<Class<?>> list=new ArrayList<Class<?>>();
   scan("com.Models",list);
   System.out.println(list.size());
    for(Class<?> cla:list){
        System.out.println(cla.getName());
    }
}
}

使用你这个打包到安卓软件发布后,调试时发现 File[] files=dir.listFiles(); 执行后,files为null
回复
kosora曹 2014-02-26
这没什么难的吧,就一个先序遍历:


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ScanPackage {
/**
 *遍历包  并遍历子包
 */
public static void scan(String packageName ,List<Class<?>> list) throws Exception{
    String path=getSrcPath()+packageToDir(packageName);
    File dir=new File(path);
    File[] files=dir.listFiles();
    Class<?> cla=null;
    for(File f:files){
        if(f.isDirectory()){
            String childName=packageName+"."+f.getName();
            scan(childName, list);

        }else{
            cla=Class.forName(packageName+"."+f.getName().split("\\.")[0]);
            list.add(cla);
        }
    }
}
/**
获取当前路径
*/
public static String getSrcPath() throws IOException{
   File file=new File("");
   String path=file.getCanonicalPath()+File.separator+"src";
   return path;
}
/**
 *package转换为路径格式
 */
public static String packageToDir(String packageName){
    String[] array=packageName.split("\\.");
    StringBuffer sb=new StringBuffer();
    for(String str:array){
        sb.append(File.separator).append(str);
    }
    return sb.toString();
}
public static void main(String[] args) throws Exception {
    List<Class<?>> list=new ArrayList<Class<?>>();
   scan("com.Models",list);
   System.out.println(list.size());
    for(Class<?> cla:list){
        System.out.println(cla.getName());
    }
}
}

回复
MoveBricksWorker 2014-02-26
/**
	 * 从一个包中找出所有的类,不包括jar包
	 * @param packageName
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("rawtypes")
	public static List<Class> getClasses(String packageName)
			throws IOException, ClassNotFoundException {
		ClassLoader classLoader = Thread.currentThread()
				.getContextClassLoader();
		String path = packageName.replace(".", "/");
		System.out.println("Path:"+path);
		Enumeration<URL> resources = classLoader.getResources(path);
		List<File> dirs = new ArrayList<File>();
		while (resources.hasMoreElements()) {
			URL urlResource = resources.nextElement();
			dirs.add(new File(urlResource.getFile()));
		}
		List<Class> classes = new ArrayList<Class>();
		for (File directory : dirs) {
			classes.addAll(findClasses(directory, packageName));
		}
		return classes;
	}

	@SuppressWarnings("rawtypes")
	private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
		List<Class> classes=new ArrayList<Class>();
		if(!directory.isDirectory()){
			return classes;
		}
		File[] files=directory.listFiles();
		for(File file:files){
			if(file.isDirectory()){
				assert !file.getName().contains(".");
				System.out.println(packageName+"."+file.getName());
				classes.addAll(findClasses(file,packageName+"."+file.getName()));
			}else if(file.getName().endsWith(".class")){
				classes.add(Class.forName(packageName+"."+file.getName().substring(0, file.getName().length()-6)));
			}
		}
		return classes;
	}
回复
知擎物联 2014-02-26
引用 9 楼 kanorl 的回复:
楼主可以看看https://code.google.com/p/reflections/
下载了那个jar并添加到了libs,并引用,按上面的示例写了代码,但放安卓一运行就异常,程序崩溃了。
回复
知擎物联 2014-02-26
引用 14 楼 msj100ff 的回复:
11楼正解 只能通过文件操作获取路径加载类,然后反射获取类信息
刚上手安卓开发,java才用了2周,能给详细代码不?
回复
ohfiner 2014-02-25
思路: 通过包名得到文件夹路劲。 通过File类列出所有文件。再根据包名+文件名进行反射
回复
raistlic 2014-02-25
引用 5 楼 raistlic 的回复:
我之前也想做同样的事,发现 Java 好像没有提供这种支持,所以应该没有简单干净的实现方法。 ClassLoader 的工作原则是,当你特别指定某一个 qualified class name 的时候才去寻找或加载那个类,而对于“目前已经加载”的类,也不提供类似基于包名的迭代查询。 一种思路是想办法获取当前运行的 jvm 的 classpath 参数,然后去文件系统检查 classpath 范围内所有的 class 文件,很脏,很费时,而且得到的结果只是某包名下“所有可能被加载的类”。 要得到“已经加载的类中属于某包名的那些”,没什么思路,应该是做不到的。——话虽如此,如果用了自定义的ClassLoader,那当然可以提供功能查询“该ClassLoader下所有属于某包名的类”。
补充: 刚刚搜了一下,发现还是有(虽然有点hacky)办法在不影响某类加载与否的前提下检查“某类是否已经加载”,这是我之前不知道的 :-) http://stackoverflow.com/questions/3678579/how-to-check-whether-a-class-is-initialized
回复
发动态
发帖子
Java SE
创建于2007-09-28

6.1w+

社区成员

Java 2 Standard Edition
申请成为版主
社区公告
暂无公告