服务器之家

服务器之家 > 正文

Java通过反射来打印类的方法实现

时间:2022-01-06 12:18     来源/作者:Zong_0915

工作了有一段时间了,我觉得是时候去复习下Java的一些基础知识,因此写下了这篇文章。平常开发过程中,前端写的比较多,后端也不能忘!

Java通过反射来打印类的方法实现

 

一. 案例出发

先准备一个模板类:

public class User {
    public int id;
    private String name;

    public User(String name, int id) {
        this.id = id;
        this.name = name;
    }

    private User(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

开始反射

import java.lang.reflect.*;

public class Test {
    public static final String LINE = "
";
    public static final String SPACE = "    ";

    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("com.User");
        // Class<?> c = Test.class.getClassLoader().loadClass("com.User");
        StringBuilder sb = new StringBuilder();
        // 打印包,类名
        String packageName = c.getPackage().getName();
        sb.append("package " + packageName + ";" + LINE);
        sb.append(LINE);
        sb.append("public class " + c.getSimpleName() + "{" + LINE);
        // 打印成员变量
        Field[] declaredFields = c.getDeclaredFields();
        for (Field field : declaredFields) {
            // Field.getModifiers()返回一个int类型的数值,用于标识public、static等标识符
            String fieldModifier = Modifier.toString(field.getModifiers());
            // 获取属性类型的简要名称
            String typeName = field.getType().getSimpleName();
            // 属性的名称
            String fieldName = field.getName();
            sb.append(SPACE + fieldModifier + " " + typeName + " " + fieldName + ";" + LINE);
        }
        sb.append(LINE);
        // 打印构造
        Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            // 构造函数的标识符
            String constructorModifier = Modifier.toString(constructor.getModifiers());
            sb.append(SPACE + constructorModifier + " " + c.getSimpleName() + " " + "(");
            // 打印构造函数的参数
            printParam(sb, constructor.getParameterTypes());
        }
        // 打印方法
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            // 方法的标识符
            String methodModifier = Modifier.toString(method.getModifiers());
            // 方法返回类型
            String returnTypeName = method.getReturnType().getSimpleName();
            // 方法名称
            String methodName = method.getName();
            sb.append(SPACE + methodModifier + " " + returnTypeName + " " + methodName + "(");
            printParam(sb, method.getParameterTypes());
        }

        sb.append("}");
        System.out.println(sb.toString());
    }

    private static void printParam(StringBuilder sb, Class<?>[] parameterTypes2) {
        Class<?>[] parameterTypes = parameterTypes2;
        for (int i = 0; i < parameterTypes.length; i++) {
            // 参数的类型
            String simpleName = parameterTypes[i].getSimpleName();
            if (i == 0) {
                sb.append(simpleName + " args");
            } else {
                sb.append(", " + simpleName + " args");
            }
        }
        sb.append(") {" + LINE);
        sb.append(SPACE + "}" + LINE);
        sb.append(LINE);
    }
}

最终的结果如下:

Java通过反射来打印类的方法实现

 

二. 反射方法的分析

 

2.1 反射的方式

代码中我们可以发现,这里提供了两种基本的反射:

  • Class.forName()
  • getClassLoader().loadClass()

首先,在模板类中添加静态块代码:

Java通过反射来打印类的方法实现

再来运行一下两种反射方式的代码:

forName

Java通过反射来打印类的方法实现

getClassLoader

Java通过反射来打印类的方法实现

结论如下:

初始化:通过forName方式反射的对象,会进行初始化(会执行静态代码),而通过getClassLoader方式反射的对象,是不会进行初始化的。

 

2.2 修饰符的打印

如果想打印方法、属性的修饰符,我们应该通过Modifier类去拿到。请看这一行代码:

String fieldModifier = Modifier.toString(field.getModifiers());

来看下Modifier.toString的源码:

public static String toString(int mod) {
    StringBuilder sb = new StringBuilder();
    int len;

    if ((mod & PUBLIC) != 0)        sb.append("public ");
    if ((mod & PROTECTED) != 0)     sb.append("protected ");
    if ((mod & PRIVATE) != 0)       sb.append("private ");

    /* Canonical order */
    if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
    if ((mod & STATIC) != 0)        sb.append("static ");
    if ((mod & FINAL) != 0)         sb.append("final ");
    if ((mod & TRANSIENT) != 0)     sb.append("transient ");
    if ((mod & VOLATILE) != 0)      sb.append("volatile ");
    if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
    if ((mod & NATIVE) != 0)        sb.append("native ");
    if ((mod & STRICT) != 0)        sb.append("strictfp ");
    if ((mod & INTERFACE) != 0)     sb.append("interface ");

    if ((len = sb.length()) > 0)    /* trim trailing space */
        return sb.toString().substring(0, len-1);
    return "";
}

很明显,其通过语言修饰符的类型(int类型)来做对应的映射并返回。
案例代码中有三块地方都支持获得修饰符类型:

  • field.getModifiers():字段修饰符。
  • constructor.getModifiers():构造修饰符。
  • method.getModifiers():方法的修饰符。

 

2.3 getDeclaredxxx和getxxx的区别

以Field为例:

Field[] declaredFields = c.getDeclaredFields();
Field[] fields = c.getFields();

案例如下:
1.新建一个Parent类:

public class Parent {
    public String parentAddress;
    private Integer Number;
}

2.让User类继承Parent

Java通过反射来打印类的方法实现

3.测试1:getDeclaredFields打印成员变量:

Java通过反射来打印类的方法实现

4.测试2:getFields打印成员变量:

Java通过反射来打印类的方法实现

两者区别如下:

 

比较内容 getDeclaredFields getFields
作用的类的范围 仅仅限于当前类 还可以包括父类
作用的修饰符范围 可以获取public和非public类型 只能获得public类型的相关值

 

 

2.4 getSimpleName和getName有什么不同

以这行代码为例:

String typeName = field.getType().getSimpleName();

若我将getSimpleName改为getName,看看输出结果会有什么不同:

Java通过反射来打印类的方法实现

可以发现gatName输出的是这个类型的全名称,那么对应的getSimpleName就顾名思义,返回的是类型名称。

对于其他的相关属性和API,代码的注释都写的比较详细了,就不展开介绍了。

到此这篇关于Java通过反射来打印类的方法实现的文章就介绍到这了,更多相关Java反射打印类内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/Zong_0915/article/details/120238079

标签:

相关文章

热门资讯

蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部