java反射获取包下所有类的操作

我就废话不多说了,大家还是直接看代码吧~

  public static void main(String[] args) {
        try {
            // 获取包名下所有类
            Set<Class<?>> classes = getClasses("com");
            for(Class c:classes){
                // 打印有RestController 的类
                if(c.isAnnotationPresent(RestController.class)){
                    System.out.println(c.getName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
     * 根据包名获取包下面所有的类名
     *
     * @param pack
     * @return
     * @throws Exception
     */
    public static Set<Class<?>> getClasses(String pack) throws Exception {
        // 第一个class类的集合
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
        // 是否循环迭代
        boolean recursive = true;
        // 获取包的名字 并进行替换
        String packageName = pack;
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        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)) {
                    // 获取包的物理路径
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    // 以文件的方式扫描整个包下的文件 并添加到集合中
                    findClassesInPackageByFile(packageName, filePath, recursive, classes);
                } else if ("jar".equals(protocol)) {
                    // 如果是jar包文件
                    // 定义一个JarFile
                    System.out.println("jar类型的扫描");
                    JarFile jar;
                    try {
                        // 获取jar
                        jar = ((JarURLConnection) url.openConnection()).getJarFile();
                        // 从此jar包 得到一个枚举类
                        Enumeration<JarEntry> entries = jar.entries();
                        findClassesInPackageByJar(packageName, entries, packageDirName, recursive, classes);
                    } catch (IOException e) {
                        // log.error("在扫描用户定义视图时从jar包获取文件出错");
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classes;
    }
/**
     * 以文件的形式来获取包下的所有Class
     *
     * @param packageName
     * @param packagePath
     * @param recursive
     * @param classes
     */
    private static void findClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, Set<Class<?>> classes) {
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            // log.warn("用户定义包名 " + packageName + " 下没有任何文件");
            return;
        }
        // 如果存在 就获取包下的所有文件 包括目录
        File[] dirfiles = dir.listFiles(new FileFilter() {
            // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
            @Override
            public boolean accept(File file) {
                return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
            }
        });
        // 循环所有文件
        for (File file : dirfiles) {
            // 如果是目录 则继续扫描
            if (file.isDirectory()) {
                findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
            } else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    // 添加到集合中去
                    // classes.add(Class.forName(packageName + '.' +
                    // className));
                    // 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
                    classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    // log.error("添加用户自定义视图类错误 找不到此类的.class文件");
                    e.printStackTrace();
                }
            }
        }
    }
 /**
     * 以jar的形式来获取包下的所有Class
     *
     * @param packageName
     * @param entries
     * @param packageDirName
     * @param recursive
     * @param classes
     */
    private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, final boolean recursive, Set<Class<?>> classes) {
        // 同样的进行循环迭代
        while (entries.hasMoreElements()) {
            // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
            JarEntry entry = entries.nextElement();
            String name = entry.getName();
            // 如果是以/开头的
            if (name.charAt(0) == '/') {
                // 获取后面的字符串
                name = name.substring(1);
            }
            // 如果前半部分和定义的包名相同
            if (name.startsWith(packageDirName)) {
                int idx = name.lastIndexOf('/');
                // 如果以"/"结尾 是一个包
                if (idx != -1) {
                    // 获取包名 把"/"替换成"."
                    packageName = name.substring(0, idx).replace('/', '.');
                }
                // 如果可以迭代下去 并且是一个包
                if ((idx != -1) || recursive) {
                    // 如果是一个.class文件 而且不是目录
                    if (name.endsWith(".class") && !entry.isDirectory()) {
                        // 去掉后面的".class" 获取真正的类名
                        String className = name.substring(packageName.length() + 1, name.length() - 6);
                        try {
                            // 添加到classes
                            classes.add(Class.forName(packageName + '.' + className));
                        } catch (ClassNotFoundException e) {
                            // .error("添加用户自定义视图类错误 找不到此类的.class文件");
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

补充:通过java反射机制获取该类的所有属性类型、值、

方法使用了这俩个包下的 field 和method

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public static void getObjectValue(Object object) throws Exception {
		//我们项目的所有实体类都继承BaseDomain (所有实体基类:该类只是串行化一下)
		//不需要的自己去掉即可
		if (object != null && object instanceof BaseDomain) {//if (object!=null )  ----begin
			// 拿到该类
			Class<?> clz = object.getClass();
			// 获取实体类的所有属性,返回Field数组
			Field[] fields = clz.getDeclaredFields();

			for (Field field : fields) {// --for() begin
				System.out.println(field.getGenericType());//打印该类的所有属性类型

				// 如果类型是String
				if (field.getGenericType().toString().equals(
						"class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
					// 拿到该属性的gettet方法
					/**
					 * 这里需要说明一下:他是根据拼凑的字符来找你写的getter方法的
					 * 在Boolean值的时候是isXXX(默认使用ide生成getter的都是isXXX)
					 * 如果出现NoSuchMethod异常 就说明它找不到那个gettet方法 需要做个规范
					 */
					Method m = (Method) object.getClass().getMethod(
							"get" + getMethodName(field.getName()));

					String val = (String) m.invoke(object);// 调用getter方法获取属性值
					if (val != null) {
						System.out.println("String type:" + val);
					}
				}

				// 如果类型是Integer
				if (field.getGenericType().toString().equals(
						"class java.lang.Integer")) {
					Method m = (Method) object.getClass().getMethod(
							"get" + getMethodName(field.getName()));
					Integer val = (Integer) m.invoke(object);
					if (val != null) {
						System.out.println("Integer type:" + val);
					}
				}

				// 如果类型是Double
				if (field.getGenericType().toString().equals(
						"class java.lang.Double")) {
					Method m = (Method) object.getClass().getMethod(
							"get" + getMethodName(field.getName()));
					Double val = (Double) m.invoke(object);
					if (val != null) {
						System.out.println("Double type:" + val);
					}
				}

				// 如果类型是Boolean 是封装类
				if (field.getGenericType().toString().equals(
						"class java.lang.Boolean")) {
					Method m = (Method) object.getClass().getMethod(
							field.getName());
					Boolean val = (Boolean) m.invoke(object);
					if (val != null) {
						System.out.println("Boolean type:" + val);
					}
				}

				// 如果类型是boolean 基本数据类型不一样 这里有点说名如果定义名是 isXXX的 那就全都是isXXX的
				// 反射找不到getter的具体名
				if (field.getGenericType().toString().equals("boolean")) {
					Method m = (Method) object.getClass().getMethod(
							field.getName());
					Boolean val = (Boolean) m.invoke(object);
					if (val != null) {
						System.out.println("boolean type:" + val);
					}
				}
				// 如果类型是Date
				if (field.getGenericType().toString().equals(
						"class java.util.Date")) {
					Method m = (Method) object.getClass().getMethod(
							"get" + getMethodName(field.getName()));
					Date val = (Date) m.invoke(object);
					if (val != null) {
						System.out.println("Date type:" + val);
					}

				}
				// 如果类型是Short
				if (field.getGenericType().toString().equals(
						"class java.lang.Short")) {
					Method m = (Method) object.getClass().getMethod(
							"get" + getMethodName(field.getName()));
					Short val = (Short) m.invoke(object);
					if (val != null) {
						System.out.println("Short type:" + val);
					}
				}
				// 如果还需要其他的类型请自己做扩展

			}//for() --end

		}//if (object!=null )  ----end
	}

	// 把一个字符串的第一个字母大写、效率是最高的、
	private static String getMethodName(String fildeName) throws Exception{
		byte[] items = fildeName.getBytes();
		items[0] = (byte) ((char) items[0] - 'a' + 'A');
		return new String(items);
	}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • JAVA基础之注解与反射的使用方法和场景

    注解 注解定义 Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制. Java 语言中的类.方法.变量.参数和包等都可以被标注.和注释不同,Java 标注可以通过反射获取标注内容.在编译器生成类文件时,标注可以被嵌入到字节码中.Java 虚拟机可以保留标注内容,在运行 时可以获取到标注内容 . 当然它也支持自定义 Java 标注. 注解与注释的区别:注解是给机器看的注释,而注释是给程序员看的提示,编译时自动忽略注释. 使用场景 编译格式检查 反射中解

  • java 非常好用的反射框架Reflections介绍

    Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据. 使用Reflections可以很轻松的获取以下元数据信息: 1)获取某个类型的所有子类:比如,有一个父类是TestInterface,可以获取到TestInterface的所有子类. 2)获取某个注解的所有类型/字段变量,支持注解参数匹配. 3)使用正则表达式获取所有匹配的资源文件 4)获取特定签名方法. 通常的用法有: 引入依赖jar <dependency> <groupId>org

  • Java反射框架Reflections示例详解

    MAVEN 坐标 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.10</version> </dependency> Reflections 的作用 Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据. 获取某个类型的所有

  • java反射机制的一些学习心得小结

    概述 之前在了解Spring的类加载机制的时候,了解了java的反射机制.但是,我对反射理解一直不深.也一直有点疑惑:Spring为什么利用反射创建对象?直接new对象和依靠反射创建对象有什么区别?什么是动态加载类? 什么是反射? 要想知道反射到底是什么,首先需要知道java的类加载和对象创建的机制. 当我们写完一个java文件的时候,后缀是.java.在我们利用IDE执行java文件的时候,其实IDE也帮我们运行了javac,即java编译器.编译器会将.java文件编译成.class文件.j

  • Java 使用反射调用jar包中的类方式

    下面讲展示的是从image.jar包中调用image.Buddy类的方法. public class Main { public static void main(String[] args) { try { // 两种方式都可以 URL url = new File("/Users/wuchen/Documents/IntelliJIDEA/Applet/out/production/Applet/image.jar").toURI().toURL(); // URL url = n

  • Java中的注解和反射实例详解

    一.注解 注解(Annotation): 从jdk5.0开始引进,可以对程序进行解释或被其他程序读取. 注解格式:"@注释名",并可以添加一些参数. 例:@MyAnnotation(value='value') 1.内置注解 @override: 用于修饰方法,表示该方法声明是重写或实现一个父类的方法 @Deprecated: 用于修饰方法.属性.类,表示已过时不建议使用的 @SuppressWarnings: 用于抑制编译时的警告信息 2.元注解 作用:用于注解其他注解 @Targe

  • Java反射 Field类的使用全方位解析

    Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限.反射的字段可能是一个类(静态)字段或实例字段. Field 成员变量的介绍 每个成员变量有类型和值. java.lang.reflect.Field 为我们提供了获取当前对象的成员变量的类型,和重新设值的方法. 获取变量的类型 类中的变量分为两种类型:基本类型和引用类型: 基本类型( 8 种) 整数:byte, short, int, long 浮点数:float, double 字符:char 布尔值:boolean 引用类

  • java反射获取包下所有类的操作

    我就废话不多说了,大家还是直接看代码吧~ public static void main(String[] args) { try { // 获取包名下所有类 Set<Class<?>> classes = getClasses("com"); for(Class c:classes){ // 打印有RestController 的类 if(c.isAnnotationPresent(RestController.class)){ System.out.prin

  • 如何获取包下所有类中的注解的值(java工具类)

    获取包下所有类中注解的值 作用: 这个工具类主要的作用就是获取类中的注解的值. 应用场景: 做权限的时候获取@RequestMapping();的值,自动添加到数据库中. /** * getRequestMappingValue方法描述: * 作者:thh * 日期:2016年7月18日 下午5:41:00 * 异常对象:@param packageName * 异常对象:@return */ public static List<String> getRequestMappingValue(

  • Java语言Lang包下常用的工具类介绍

    无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数.你可知道,有很多现成的工具类可用,并且代码质量都很不错,不用你写,不用你调试,只要你发现. 在 Apache Jakarta Common 中, Lang 这个 Java 工具包是所有 Apache Jakarta Common 项目中被使用最广泛的,几乎你所知道的名气比较大的软件里面都有用到它,包括 Tomcat, Weblogic, Websphere, Eclipse 等等.我们就从这个包开始介绍整个 common 项

  • Java反射获取实例的速度对比分析

    之前代码有一个逻辑,是在初始化时读取某个包下的所有class文件,放入到一个HashMap里.代码运行过程中,通过Key获取到对应class的全路径名,最后通过Class.forName(className).getDeclaredConstructor().newInstance()获取实例对象. 后来同事看到了代码,对这个HashMap里存储方式提出了建议,之前的Map是<String,String>完全可以改成<String,Class> 后来我测试了一下两者实例化一个对象的

  • java 利用反射获取内部类静态成员变量的值操作

    昨晚,一同事问到我,怎么利用java反射解析内部类静态成员变量的值,于是顺手写下了. 废话不多说,直接上代码! 待解析类结构如下: /** * @Author changle * @Time 17/6/13. * @Desc to do */ public class Goods { static class apple{ public static String version = "iphone6s[是手机不是吃的苹果]"; public static String date =

  • 利用java反射机制实现自动调用类的简单方法

    1. 新建TestServlet类 package com.yanek.test; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.ht

  • java反射获取一个object属性值代码解析

    有些时候你明明知道这个object里面是什么,但是因为种种原因,你不能将它转化成一个对象,只是想单纯地提取出这个object里的一些东西,这个时候就需要用反射了. 假如你这个类是这样的: private class User { String userName; String userPassword; public String getUserName() { return userName; } public void setUserName(String userName) { this.

  • java 利用java反射机制动态加载类的简单实现

    如下所示: ////////////////// Load.java package org.bromon.reflect; import java.util.ArrayList; import java.util.List; public class Load implements Operator { @Override public List<?> act(List<?> params) { // TODO Auto-generated method stub List<

  • Java NIO Path接口和Files类配合操作文件的实例

    Path接口 1.Path表示的是一个目录名序列,其后还可以跟着一个文件名,路径中第一个部件是根部件时就是绝对路径,例如 / 或 C:\ ,而允许访问的根部件取决于文件系统: 2.以根部件开始的路径是绝对路径,否则就是相对路径: 3.静态的Paths.get方法接受一个或多个字符串,字符串之间自动使用默认文件系统的路径分隔符连接起来(Unix是 /,Windows是 \ ),这就解决了跨平台的问题,接着解析连接起来的结果,如果不是合法路径就抛出InvalidPathException异常,否则就

  • java代码获取数据库表里数据的总数操作

    在访问数据库时,特别是新手,可能会需要查询表中数据总数,以下这段代码可以非常简便的获取到数据数目 //先建立数据库连接,执行查询语句 Connection conn = DriverManager.getConnection(URL, USER, PassWord); Statement st=conn.createStatement(); ResultSet rs =st.executeQuery("select count(*) as result from tablename")

随机推荐