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

 更新时间:2021年09月17日 08:38:36   作者: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 = "\n";
    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);
    }
}

最终的结果如下:

在这里插入图片描述

二. 反射方法的分析

2.1 反射的方式

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

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

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

在这里插入图片描述

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

forName

在这里插入图片描述

getClassLoader

在这里插入图片描述

结论如下:

初始化:通过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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

两者区别如下:

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

2.4 getSimpleName和getName有什么不同

以这行代码为例:

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

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

在这里插入图片描述

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

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

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

相关文章

  • Spring web集成rabbitmq代码实例

    Spring web集成rabbitmq代码实例

    这篇文章主要介绍了Spring web集成rabbitmq代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 解决lombok的@Data注解无法打印继承的父类信息问题

    解决lombok的@Data注解无法打印继承的父类信息问题

    在Java编程中,使用@Data注解可能导致子类继承父类属性后,打印只显示子类信息不显示父类信息,问题源于@Data注解作用域仅限于当前类,解决方法包括使用@ToString(callSuper=true)注解或重写toString方法
    2024-11-11
  • Java 敏感词检测工具的实现

    Java 敏感词检测工具的实现

    本文介绍了Java敏感词检测工具的使用方法,包括依赖引入、核心方法使用实例、常规用法、自定义替换检测策略等内容,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • 新手也能看懂的SpringBoot异步编程指南(简单易懂)

    新手也能看懂的SpringBoot异步编程指南(简单易懂)

    这篇文章主要介绍了新手也能看懂的SpringBoot异步编程指南(简单易懂),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Java使用EasyExcel模版导出详细操作教程

    Java使用EasyExcel模版导出详细操作教程

    业务中经常需要按照一个特定的模板导出特定内容,有些单元格还要求特殊的格式,所以下面这篇文章主要给大家介绍了关于Java使用EasyExcel模版导出的相关资料,需要的朋友可以参考下
    2023-10-10
  • java编程题之顺时针打印矩阵

    java编程题之顺时针打印矩阵

    这篇文章主要为大家详细介绍了java编程题之顺时针打印矩阵,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • java根据模板导出PDF的详细实现过程

    java根据模板导出PDF的详细实现过程

    前段时间因为相关业务需求需要后台生成pdf文件,所以下面这篇文章主要给大家介绍了关于java根据模板导出PDF的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • 2019年最新Java学习路线图

    2019年最新Java学习路线图

    不管你是不懂电脑的小白,还是已经步入开发的大牛,这套路线路绝对不容错过,路线图的宗旨就是分享,专业,便利,让喜爱Java的人,都能平等的学习,感兴趣的同学可以了解一下
    2019-03-03
  • Java中的volatile实现机制详细解析

    Java中的volatile实现机制详细解析

    这篇文章主要介绍了Java中的volatile实现机制详细解析,本文的主要内容就在于要理解volatile的缓存的一致性协议导致的共享变量可见性,以及volatile在解析成为汇编语言的时候对变量加锁两块理论内容,需要的朋友可以参考下
    2024-01-01
  • 详解Java使用JDBC连接MySQL数据库

    详解Java使用JDBC连接MySQL数据库

    本文详细讲解了Java使用JDBC连接MySQL数据库的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01

最新评论