java通过全类名获取本类以及父类的字段名称以及获取指定包名下的所有类的全类名的解决方案

  1. 获取指定包名下的所有类的全类名的解决方案转载至https://www.cnblogs.com/zeng1994/p/59313120e95e2074981870c787cd69d9.html
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.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 .
 */

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 = packageName.replaceAll("\\.", "/");

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        try {

            Enumeration<URL> urls = loader.getResources(suffixPath);

            while (urls.hasMoreElements()) {

                URL url = urls.nextElement();

                if (url != null) {

                    String protocol = url.getProtocol();

                    if ("file".equals(protocol)) {

                        String path = url.getPath();

                        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));

                        }

                    }

                }

            }

        } 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 (!file.exists()) {

            return result;

        }

        if (file.isFile()) {

            String path = file.getPath();

            // 注意:这里替换文件分割符要用replace。因为replaceAll里面的参数是正则表达式,而windows环境中File.separator="\\"的,因此会有问题

            if (path.endsWith(CLASS_SUFFIX)) {

                path = path.replace(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 : listFiles) {

                    if (flag) {

                        result.addAll(getAllClassNameByFile(f, flag));

                    } else {

                        if (f.isFile()) {

                            String path = f.getPath();

                            if (path.endsWith(CLASS_SUFFIX)) {

                                path = path.replace(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
     */

    private static List<String> getAllClassNameByJar(JarFile jarFile, String packageName, boolean flag) {

        List<String> result = new ArrayList<>();

        Enumeration<JarEntry> entries = jarFile.entries();

        while (entries.hasMoreElements()) {

            JarEntry jarEntry = entries.nextElement();

            String name = jarEntry.getName();

            // 判断是不是class文件

            if (name.endsWith(CLASS_SUFFIX)) {

                name = name.replace(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;
    }
}
  1. 通过全类名获取本类以及父类的字段名称
public class GetFieldsTest {
        public void getFields() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
            List<String> clazzNameList = ClazzUtils.getClazzName("com.entity", true);
            for (String clazzName : clazzNameList) {
                /*创建对象*/
                Class clazz = Class.forName(clazzName).newInstance().getClass();
                /*当前类字段数组*/
                Field[] thisClazzFields = clazz.getDeclaredFields();
                /*超类字段数组*/
                Field[] superclassFields = clazz.getSuperclass().getDeclaredFields();
                /*获取本类属性*/
                for (int i = 0; i < thisClazzFields.length; i++) {
                    /*由于private不允许直接访问,需要调下setAccessible,否则会报错Method threw 'java.lang.IllegalAccessException' exception.*/
                    thisClazzFields[i].setAccessible(true);
                    /*字段名称*/
                    String fileldName = thisClazzFields[i].getName();
                }
                /*获取超类属性*/
                for (int i = 0; i < superclassFields.length; i++) {
                    /*由于private不允许直接访问,需要调下setAccessible,否则会报错Method threw 'java.lang.IllegalAccessException' exception.*/
                    superclassFields[i].setAccessible(true);
                    /*字段名称*/
                    String fileldName = superclassFields[i].getName();
                }
            }
        }
    }

你可能感兴趣的:(java通过全类名获取本类以及父类的字段名称以及获取指定包名下的所有类的全类名的解决方案)