服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java通过反射来打印类的方法实现

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

2022-01-06 12:18Zong_0915 Java教程

本文主要介绍了Java通过反射来打印类的方法实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

工作了有一段时间了,我觉得是时候去复习下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

延伸 · 阅读

精彩推荐