zoukankan      html  css  js  c++  java
  • Class类工具

    Class类工具,提供操作class类的方法。<br/>
    比如:获知类、方法上是否有注解,获取类注解,获取某package下所有class等。

     

    源码如下:(点击下载 - ClassUtils.java )

      1 import java.io.File;
      2 import java.io.FileFilter;
      3 import java.io.IOException;
      4 import java.lang.annotation.Annotation;
      5 import java.lang.reflect.Field;
      6 import java.lang.reflect.Method;
      7 import java.net.JarURLConnection;
      8 import java.net.URL;
      9 import java.net.URLDecoder;
     10 import java.util.ArrayList;
     11 import java.util.Enumeration;
     12 import java.util.LinkedHashSet;
     13 import java.util.List;
     14 import java.util.Set;
     15 import java.util.jar.JarEntry;
     16 import java.util.jar.JarFile;
     17 
     18 /**
     19  * Class类工具
     20  * 
     21  */
     22 public class ClassUtils {
     23 
     24     /**
     25      * 是否有注解
     26      *
     27      * @param clazz
     28      *            a {@link java.lang.Class} object.
     29      * @param annotationClass
     30      *            a {@link java.lang.Class} object.
     31      * @return a boolean.
     32      */
     33     public static boolean hasClassAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
     34         return getClassAnnotation(clazz, annotationClass) != null;
     35     }
     36 
     37     /**
     38      * 是否有注解
     39      *
     40      * @param clazz
     41      *            a {@link java.lang.Class} object.
     42      * @param annotationClass
     43      *            a {@link java.lang.Class} object.
     44      * @param fieldName
     45      *            a {@link java.lang.String} object.
     46      * @throws cn.yicha.commons.exception.YichaException
     47      *             if any.
     48      * @return a boolean.
     49      */
     50     public static boolean hasFieldAnnotation(Class<?> clazz,
     51             Class<? extends Annotation> annotationClass, String fieldName) throws Exception {
     52         return getFieldAnnotation(clazz, annotationClass, fieldName) != null;
     53     }
     54 
     55     /**
     56      * 是否有注解
     57      *
     58      * @param clazz
     59      *            a {@link java.lang.Class} object.
     60      * @param annotationClass
     61      *            a {@link java.lang.Class} object.
     62      * @param methodName
     63      *            a {@link java.lang.String} object.
     64      * @param paramType
     65      *            a {@link java.lang.Class} object.
     66      * @throws cn.yicha.commons.exception.YichaException
     67      *             if any.
     68      * @return a boolean.
     69      */
     70     public static boolean hasMethodAnnotation(Class<?> clazz,
     71             Class<? extends Annotation> annotationClass, String methodName, Class<?>... paramType) throws Exception {
     72         return getMethodAnnotation(clazz, annotationClass, methodName, paramType) != null;
     73     }
     74 
     75     /**
     76      * 获取类注解
     77      *
     78      * @param clazz
     79      *            类
     80      * @param annotationClass
     81      *            注解类
     82      * @return a A object.
     83      */
     84     public static <A extends Annotation> A getClassAnnotation(Class<?> clazz, Class<A> annotationClass) {
     85         return clazz.getAnnotation(annotationClass);
     86     }
     87 
     88     /**
     89      * 获取类成员注解
     90      *
     91      * @param clazz
     92      *            类
     93      * @param annotationClass
     94      *            注解类
     95      * @param fieldName
     96      *            成员属性名
     97      * @throws cn.yicha.commons.exception.YichaException
     98      *             if any.
     99      * @return a A object.
    100      */
    101     public static <A extends Annotation> A getFieldAnnotation(Class<?> clazz,
    102             Class<A> annotationClass, String fieldName) throws Exception {
    103         try {
    104             Field field = clazz.getDeclaredField(fieldName);
    105             if (field == null) {
    106                 throw new Exception("no such field[" + fieldName + "] in " + clazz.getCanonicalName());
    107             }
    108             return field.getAnnotation(annotationClass);
    109         } catch (SecurityException e) {
    110             e.printStackTrace();
    111             throw new Exception("access error: field[" + fieldName + "] in " + clazz.getCanonicalName(), e);
    112         } catch (NoSuchFieldException e) {
    113             e.printStackTrace();
    114             throw new Exception("no such field[" + fieldName + "] in " + clazz.getCanonicalName());
    115         }
    116     }
    117 
    118     /**
    119      * 获取类方法上的注解
    120      *
    121      * @param clazz
    122      *            类
    123      * @param annotationClass
    124      *            注解类
    125      * @param methodName
    126      *            方法名
    127      * @param paramType
    128      *            方法参数
    129      * @throws cn.yicha.commons.exception.YichaException
    130      *             if any.
    131      * @return a A object.
    132      */
    133     public static <A extends Annotation> A getMethodAnnotation(Class<?> clazz,
    134             Class<A> annotationClass, String methodName, Class<?>... paramType)
    135             throws Exception {
    136         try {
    137             Method method = clazz.getDeclaredMethod(methodName, paramType);
    138             if (method == null) {
    139                 throw new Exception("access error: method[" + methodName + "] in " + clazz.getCanonicalName());
    140             }
    141             return method.getAnnotation(annotationClass);
    142         } catch (SecurityException e) {
    143             e.printStackTrace();
    144             throw new Exception("access error: method[" + methodName + "] in " + clazz.getCanonicalName(), e);
    145         } catch (NoSuchMethodException e) {
    146             e.printStackTrace();
    147             throw new Exception("no such method[" + methodName + "] in " + clazz.getCanonicalName(), e);
    148         }
    149     }
    150 
    151     /**
    152      * 从包package中获取所有的Class
    153      *
    154      * @param pagekageName
    155      *            包名
    156      * @param recursive
    157      *            是否递归
    158      * @return a {@link java.util.Set} object.
    159      */
    160     public static Set<Class<?>> getClasses(String pagekageName, boolean recursive) {
    161         // 第一个class类的集合
    162         Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
    163         // 获取包的名字 并进行替换
    164         String packageName = pagekageName;
    165         String packageDirName = packageName.replace('.', '/');
    166         // 定义一个枚举的集合 并进行循环来处理这个目录下的things
    167         Enumeration<URL> dirs;
    168         try {
    169             dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
    170             // 循环迭代下去
    171             while (dirs.hasMoreElements()) {
    172                 // 获取下一个元素
    173                 URL url = dirs.nextElement();
    174                 // 得到协议的名称
    175                 String protocol = url.getProtocol();
    176                 // 如果是以文件的形式保存在服务器上
    177                 if ("file".equals(protocol)) {
    178                     // 获取包的物理路径
    179                     String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
    180                     // 以文件的方式扫描整个包下的文件 并添加到集合中
    181                     findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
    182                 } else if ("jar".equals(protocol)) {
    183                     // 如果是jar包文件
    184                     // 定义一个JarFile
    185                     JarFile jar;
    186                     try {
    187                         // 获取jar
    188                         jar = ((JarURLConnection) url.openConnection()).getJarFile();
    189                         // 从此jar包 得到一个枚举类
    190                         Enumeration<JarEntry> entries = jar.entries();
    191                         // 同样的进行循环迭代
    192                         while (entries.hasMoreElements()) {
    193                             // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
    194                             JarEntry entry = entries.nextElement();
    195                             String name = entry.getName();
    196                             // 如果是以/开头的
    197                             if (name.charAt(0) == '/') {
    198                                 // 获取后面的字符串
    199                                 name = name.substring(1);
    200                             }
    201                             // 如果前半部分和定义的包名相同
    202                             if (name.startsWith(packageDirName)) {
    203                                 int idx = name.lastIndexOf('/');
    204                                 // 如果以"/"结尾 是一个包
    205                                 if (idx != -1) {
    206                                     // 获取包名 把"/"替换成"."
    207                                     packageName = name.substring(0, idx)
    208                                             .replace('/', '.');
    209                                 }
    210                                 // 如果可以迭代下去 并且是一个包
    211                                 if ((idx != -1) || recursive) {
    212                                     // 如果是一个.class文件 而且不是目录
    213                                     if (name.endsWith(".class") && !entry.isDirectory()) {
    214                                         // 去掉后面的".class" 获取真正的类名
    215                                         String className = name.substring(packageName.length() + 1, name.length() - 6);
    216                                         try {
    217                                             // 添加到classes
    218                                             classes.add(Class.forName(packageName + '.' + className));
    219                                         } catch (ClassNotFoundException e) {
    220                                             e.printStackTrace();
    221                                             // log
    222                                             // .error("添加用户自定义视图类错误 找不到此类的.class文件");
    223                                         }
    224                                     }
    225                                 }
    226                             }
    227                         }
    228                     } catch (IOException e) {
    229                         // log.error("在扫描用户定义视图时从jar包获取文件出错");
    230                         throw new RuntimeException(e);
    231                     }
    232                 }
    233             }
    234         } catch (IOException e) {
    235             e.printStackTrace();
    236         }
    237 
    238         return classes;
    239     }
    240 
    241     /**
    242      * 以文件的形式来获取包下的所有Class
    243      *
    244      * @param packageName
    245      *            a {@link java.lang.String} object.
    246      * @param packagePath
    247      *            a {@link java.lang.String} object.
    248      * @param recursive
    249      *            a boolean.
    250      * @param classes
    251      *            a {@link java.util.Set} object.
    252      */
    253     public static void findAndAddClassesInPackageByFile(String packageName,
    254             String packagePath, final boolean recursive, Set<Class<?>> classes) {
    255         // 获取此包的目录 建立一个File
    256         File dir = new File(packagePath);
    257         // 如果不存在或者 也不是目录就直接返回
    258         if (!dir.exists() || !dir.isDirectory()) {
    259             // log.warn("用户定义包名 " + packageName + " 下没有任何文件");
    260             return;
    261         }
    262         // 如果存在 就获取包下的所有文件 包括目录
    263         File[] dirfiles = dir.listFiles(new FileFilter() {
    264             // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
    265             public boolean accept(File file) {
    266                 return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
    267             }
    268         });
    269         // 循环所有文件
    270         for (File file : dirfiles) {
    271             // 如果是目录 则继续扫描
    272             if (file.isDirectory()) {
    273                 findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
    274             } else {
    275                 // 如果是java类文件 去掉后面的.class 只留下类名
    276                 String className = file.getName().substring(0, file.getName().length() - 6);
    277                 try {
    278                     // 添加到集合中去
    279                     classes.add(Class.forName(packageName + '.' + className));
    280                 } catch (ClassNotFoundException e) {
    281                     // log.error("添加用户自定义视图类错误 找不到此类的.class文件");
    282                     e.printStackTrace();
    283                 }
    284             }
    285         }
    286     }
    287 
    288     /**
    289      * <p>
    290      * Description:给一个接口,返回这个接口同一个包下的所有实现类
    291      * </p>
    292      *
    293      * @param c
    294      *            a {@link java.lang.Class} object.
    295      * @return a {@link java.util.List} object.
    296      */
    297     public static List<Class<?>> getAllClassByInterface(Class<?> c) {
    298         List<Class<?>> returnClassList = new ArrayList<Class<?>>(); // 返回结果
    299         // 如果不是一个接口,则不做处理
    300         if (!c.isInterface()) {
    301             return returnClassList;
    302         }
    303         String packageName = c.getPackage().getName(); // 获得当前的包名
    304         Set<Class<?>> allClass = getClasses(packageName, true); // 获得当前包下以及子包下的所有类
    305         // 判断是否是同一个接口
    306         for (Class<?> clazz : allClass) {
    307             if (c.isAssignableFrom(clazz)) { // 判断是不是一个接口
    308                 if (!c.equals(clazz)) { // 本身不加进去
    309                     returnClassList.add(clazz);
    310                 }
    311             }
    312         }
    313         return returnClassList;
    314     }
    315 
    316 }
  • 相关阅读:
    golang框架对比Revel and Beego
    Gin框架系列02:路由与参数
    用cp命令拷贝文件,源目录后带不带斜杠的区别
    Isilon Gen6的换盘步骤
    如何在同一行里执行多个linux命令?
    KB,MB,GB,TB,PB,EB,ZB,YB,BB
    Isilon的WebUI上指定跨时区时间的小问题
    用Powershell强制同步Windows主机与Internet time server的时间
    Remote Desktop突然不能用了 “This could be due to CredSSP encryption oracle remediation”
    打开KVM Console的一些注意事项
  • 原文地址:https://www.cnblogs.com/zhoubang521/p/5200597.html
Copyright © 2011-2022 走看看