Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Java】反射简介,利用反射打印一个类当中的构造函数,方法和属性。

【Java】反射简介,利用反射打印一个类当中的构造函数,方法和属性。

作者头像
哈__
发布于 2024-04-08 13:24:58
发布于 2024-04-08 13:24:58
19500
代码可运行
举报
文章被收录于专栏:哈哈熊哈哈熊
运行总次数:0
代码可运行
我想要通过反射来打印如下效果的类信息。

Student类如下代码所示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.my.reflect;

public class Student {
    public String name;
    public int age;

    public Student(){}
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private void test(String str){
        System.out.println("哈哈哈"+str);
    }
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

你是否有思路?如果你不了解反射的话,我来给大家简单的介绍一下反射的使用方法。

一、反射简介

1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。 2、Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

在具体的东西,本文章不在这里叙述,总而言之,我们可以通过反射获取一个类的class对象,并且通过这个class对象获得这个类当中的信息。就是说,只要我能知道是哪个类,那么这个类对于我来说基本上就是透明的了。

二、反射的一些常用方法

1.获取一个类的class对象的三种方法

通过包名获取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Class clazz = Class.forName("com.my.reflect.Student");

通过类获取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Class clazz = Student.class;

通过类的对象获取 (能够拿到这个类的对象但是不知道是什么类,你可以假定下边的代码没有第一行,只有第二行,那么你能否知道s是哪个类的对象?)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Student s = new Studnet();
Class clazz = s.getClass();

以上三种获取方式相同,但是需要区分不同的场景采取不同的获取方式。

2.获取一个类的构造函数

通过class对象我们可以获取这个类的构造函数。传入的参数是一些class对象,通过这些class对象能确定你要获取的是哪个构造函数,例如下边代码。我们获取的构造函数有两个参数,第一个参数是String类型,第二个参数是int类型,通过这两个class对象,我们能够正确的获取构造参数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//class.getConstructor(Class<?>... parameterTypes)
Constructor constructor= clazz.getConstructor(String.class,int.class);
//public Student(String name,int age){}

//获取类的全部构造函数
Constructor [] constructors= clazz.getConstructors();

3.获取一个类的方法

通过调用如下代码获取一个类的方法。注意参数,第一个参数是name,代表着你想要获取的方法的名称,第二个参数不陌生了吧,在上边我们获取构造函数的时候见过,这个参数就代表着你要获取的方法的参数类型都是什么,防止方法重载的影响。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//getMethod(String name, Class<?>... parameterTypes)
Method method = clazz.getMethod();
//获取全部的方法 不需要传参
Method [] method = clazz.getMethods();

我们都知道在一个类中,方法有public修饰也有private修饰,还有protected和什么都不写,那么我们在获取Method的时候,我们只能获得类中的公有方法,私有方法我们是无法获取的,这时候就要用到下边的方法来获取一个类中的私有方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Method method = clazz.getDeclaredMethod();
//获取全部的方法,包括私有 不需要传参
Method [] methods = clazz.getDeclaredMethods();

写了这行代码,不管你的方法是共有的还是私有的都可以获取到。

4.获取一个类中的属性

通过下边的代码来获取一个类当中的属性。传入的name就是要获取的属性的名称。当然除了获取单个的属性外我们还可以获取全部的属性。如果你想要获取私有属性同样的要调用带有Declared的方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//getField(String name)
Field field =  clazz.getField();
//不需要传入参数
Field [] fields =  clazz.getFields();
// 获取单个私有属性  
Field  privateField =  clazz.getDeclaredField(name);
// 获取全部私有属性 不要参数
Field  [] allPrivateField =  clazz.getDeclaredField();

5.获取一个类、方法和属性的修饰符

我们都知道类、方法和属性都是有修饰符的,如public、final、private、static等,我们可以通过调用以下的方法来获取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Class clazz = Class.forName("com.my.reflect.Student");
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        int modifiers = constructor.getModifiers();
        System.out.println(modifiers);
        System.out.println(Modifier.toString(modifiers));

        Method method = clazz.getDeclaredMethod("test",String.class);
        int modifiers1 = method.getModifiers();
        System.out.println(modifiers1);
        System.out.println(Modifier.toString(modifiers1));

结果如下所示。

这个modifers到底该如何使用呢,别急这里有一张表格。

modifier的值是一个累加的结果,大家可以自己试一试。在上边的代码中我们能够看到,构造方法和普通方法都可以调用 getModifiers()方法,当然属性也可以。

以上就要反射的简单介绍,在这片文章中我并没有介绍通过class获取的constructor、method和field该如何使用,以后有机会的话我会发一篇文章介绍,我这篇文章主要的目的是解决一开始的问题。

三、问题解决

有了上面的基础之后,我们来解决问题,要打印一个类的信息,我们先要打印这是哪个类。这里用到了一个getSuperclass方法,获取这个类的父类的class对象,帮助我们打印继承关系。下边我们先打印了这个类的修饰符public 然后打印了类名,通过调用getName方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try{
            Class c1 = Class.forName("com.my.reflect.Student");
            Class superc1 = c1.getSuperclass();

            //获取类的修饰符
            String modifiers = Modifier.toString(c1.getModifiers());
             System.out.print(modifiers);
            System.out.print(" class "+c1.getName());
            if(modifiers.length()>=0) System.out.println(" extends "+superc1.getName());
            System.out.print("\n{\n");
            System.out.print("\n}\n");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

结果如下。是不是有些样子了?

现在我们打印构造函数。构造方法不止一个,我们调用的是getDeclaredConstructors(),之后进行for循环遍历,每一个获取到的constructor对象我们获取他的名称,获取这个构造方法的修饰符,然后打印。这时问题来了,一个方法是有参数的,我们需要获取这个构造方法的所有参数信息。这里调用getParameterTypes()方法,然后对所有的参数类型进行for循环进行遍历,然后打印这个方法的所有的参数的类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void printConstrctors(Class c1){
        Constructor[] constructors = c1.getDeclaredConstructors();
        for(Constructor c:constructors){
            String name = c.getName();
            System.out.print("   ");
            //获取构造方法的作用域
            String modifiers = Modifier.toString(c1.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.print(name+"(");

            Class[] paramTypes = c.getParameterTypes();
            for(int j = 0;j< paramTypes.length;j++){
                if(j>0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(")");
        }
    }

看结果。

之后就是我们的方法了,既然构造函数会打印了,方法是一个道理。不在讲解了。注意一个resType,也就是返回值类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public static void printMethods(Class c1){

        Method[] methods = c1.getDeclaredMethods();
        for(Method m:methods){
            Class resType = m.getReturnType();
            String name = m.getName();
            System.out.print("    ");
            String modifiers = Modifier.toString(m.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.print(resType.getName()+" "+name+"(");
            Class [] paramTypes = m.getParameterTypes();
            for(int j = 0;j< paramTypes.length;j++){
                if(j>0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(")");
        }
    }

最后就是我们的属性了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void printFields(Class c1){
        Field [] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();
            String name = field.getName();
            System.out.print("    ");
            String modifiers = Modifier.toString(field.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.println(type.getName()+" "+name+";");
        }
    }

完美解决。

四、完整代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ReflectTest {
    public static void main(String[] args) {
        try{
            Class c1 = Class.forName("com.my.reflect.Student");
            Class superc1 = c1.getSuperclass();

            //获取类的作用域
            String modifiers = Modifier.toString(c1.getModifiers());
            System.out.print(modifiers);
            System.out.print(" class "+c1.getName());
            if(modifiers.length()>=0) System.out.println(" extends "+superc1.getName());
            System.out.print("\n{\n");
            printConstrctors(c1);
            System.out.println();
            printMethods(c1);
            System.out.println();
            printFields(c1);
            System.out.print("\n}\n");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void printConstrctors(Class c1){
        Constructor[] constructors = c1.getDeclaredConstructors();
        for(Constructor c:constructors){
            String name = c.getName();
            System.out.print("   ");
            //获取构造方法的作用域
            String modifiers = Modifier.toString(c1.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.print(name+"(");

            Class[] paramTypes = c.getParameterTypes();
            for(int j = 0;j< paramTypes.length;j++){
                if(j>0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(")");
        }
    }

    public static void printMethods(Class c1){

        Method[] methods = c1.getDeclaredMethods();
        for(Method m:methods){
            Class resType = m.getReturnType();
            String name = m.getName();
            System.out.print("    ");
            String modifiers = Modifier.toString(m.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.print(resType.getName()+" "+name+"(");
            Class [] paramTypes = m.getParameterTypes();
            for(int j = 0;j< paramTypes.length;j++){
                if(j>0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(")");
        }
    }

    public static void printFields(Class c1){
        Field [] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();
            String name = field.getName();
            System.out.print("    ");
            String modifiers = Modifier.toString(field.getModifiers());
            if(modifiers.length()>0) System.out.print(modifiers+" ");
            System.out.println(type.getName()+" "+name+";");
        }
    }


}

如果对您有帮助,希望可以博主一个关注。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java基础系列(二十二):初识反射
反射的作用用一句简单的话来将就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少。
山禾说
2019/01/21
3230
java反射简明示例
Java反射在我们Java学习的过程中是非常重要的知识点。可能有些同学认为这个学习起来不容易理解,其实就我个人而言还是比较简单,学习起来也比较容易理解。下面我给大家总结一下Java反射学习的要点,同时给出几个比较好的例子。   1、Java反射的概念   反射含义:可以获取正在运行的Java对象。   2、Java反射的功能   1)可以判断运行时对象所属的类   2)可以判断运行时对象所具有的成员变量和方法   3)通过反射甚至可以调用到private的方法   4)生成动态代理   3、
java达人
2018/01/31
5900
5.7(1) 反射
5.7 反射 反射(reflection library)提供了动态操作java代码程序的方法,这项功能被大量应用于JavaBean中,使用反射,在设计或运行添加新类的时候,能够快速地应用开发工具动态查找新添加类的能力。   能够分析类能力的程序叫做反射(reflective)。   在运行中分析类的能力;       在运行中查看对象;       实现通用的数组操作代码;       利用Method对象。 5.7.1 Class类 在程序运行期间,java运行时系统始终为所有的对象维护一个被称为运
Mister24
2018/05/14
6350
猿学-深入理解Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
黑客联盟
2018/08/18
4390
猿学-深入理解Java中的反射机制
【Java入门提高篇】Day13 Java中的反射机制
  前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了。最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感觉很多人忙于把自己的知识变现,相对的在沉淀上做的实际还不够,我对此暂时还没有什么想法,总觉得,慢慢来,会更快一点,自己掌握好节奏就好。   好了,言归正传。   反射机制是Java中的一个很强大的特性,可以在运行时获取类的信息,比如说类的父类,接口,全部方法名及参数,全部常量和变量,可以说类在反射面前已经衣不遮体了(咳咳,这是正规车)。先举一个小栗子
弗兰克的猫
2018/03/19
7540
Java---类反射(1)---类反射入门和基础
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
谙忆
2021/01/21
5710
Java---类反射(1)---类反射入门和基础
Java基础巩固——反射
什么是反射 ----    反射机制就是指程序运行时能够获取自身的信息。在Java中,只要给出类的名字,就可以通过反射机制来获取类的信息 哪里用的到反射机制 ----    在jdbc中就是使用的反射来实例化对象,比如:Class.forName("com.mysql.jdbc.Driver.class").newInstance();    框架都用到反射机制,spring,hibernate、struts都是用反射机制实现的。 反射机制的优点和缺点 ----   为什么要用反射机制?直接创建对象不就可以
Janti
2018/04/10
5570
Java反射实战
  最近的项目中需要使用到Java 反射的知识,以前不怎么了解,也基本没怎么用过,抽出一片时间,来具体学习和实战下Java的反射!拿来和大家分享以及记录方便以后学习!
阿豪聊干货
2018/08/09
9400
大数据必学Java基础(九十):通过反射获取运行时类的完整结构
问题1:创建Person的对象,以后用new Person()创建,还是用反射创建?
Lansonli
2022/12/13
5150
大数据必学Java基础(九十):通过反射获取运行时类的完整结构
浅谈 Java 反射技术
反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。
Java极客技术
2022/12/02
3430
Java基础(二十三):反射机制
(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类 (2)interface:接口 (3)[]:数组 (4)enum:枚举在这里插入代码片 (5)annotation:注解@interface (6)primitive type:基本数据类型 (7)void
冬天vs不冷
2025/01/21
1130
Java基础(二十三):反射机制
Java之反射机制详解「建议收藏」
通过java语言中的反射机制可以操作字节码文件。有点类似于黑客(可以读和修改字节码文件。)通过反射机制可以操作代码片段。(class文件)让程序更加灵活。
全栈程序员站长
2022/09/08
5030
java反射03-查看方法修饰符
通过反射可以获取类的修饰符,主要方法: Class.getModifiers() 返回一个用于描述Field、Method和Constructor的修饰符的整形数值,该数值代表的含义可通过Modifier这个类分析。 Modifier 类它提供了有关Field、Method和Constructor等的访问修饰符的信息,主要的方法有:toString(int modifiers); 返回: 整形数值modifiers代表的修饰符的字符串;
潇洒
2023/10/20
1860
java反射03-查看方法修饰符
初探java安全之反射(1)
上次和亮去接了个渗透的比赛,结果我还是啥都不会,当时意识到现在大多数的网站的后端都基本上是 java 和 go了,想 php 的基本上比较少了,php 在以后肯定会没落的,java不想 php 那样 简单易用且灵活,所以很有必要系统性的学习一下java安全。
pankas
2022/10/08
2680
初探java安全之反射(1)
java反射原理
  简单来说,反射可以帮助我们在动态运行的时候,对于任意一个类,可以获取其所有的方法(包括public、protected、private和默认状态的),所有的变量(包括public、protected、private和默认状态的)。
Java阿呆
2020/11/04
5940
java反射原理
java反射技术
想必开发过接口的童鞋们,应该或多或少写过一些接口说明文档。那么,有没有可能把现有的接口做成一个界面在页面展现出来而不用去写什么接口文档,在页面展示的信息包括接口名,入参,属性,注释…… 如果有提供这些接口信息的池的话就用池的方式来做,我觉得做起来也挺方便的,效率也高。如果项目中没有这样的池,可以考虑用反射的方式来实现。那么,今天先来回顾一下java反射机制。关于反射的介绍,了解请看 官方文档。
wblearn
2018/08/27
5250
java反射技术
Java复习3-类的继承
本次学习面向对象设计的另外一个基本概念:继承(inheritance)。这是Java程序设计中的一项核心技术。另外,还要学习反射(reflection)的概念。
Ryan-Miao
2018/08/01
6680
Java反射机制详解
对于一般的开发者,很少需要直接使用Java反射机制来完成功能开发,但是反射是很多框架譬如 Spring, Mybatis 实现的核心,反射虽小,能量却很大。
小旋锋
2019/01/21
5990
Java桥方法
Java桥方法的出现是由于Java中泛型在虚拟机中会类型擦除,为了解决因擦除引起在多态时会引起问题而引入桥方法这个概念
doper
2022/09/26
3730
Java桥方法
Java反射(超详细!)[通俗易懂]
通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件。) 通过反射机制可以操作代码片段。(class文件。)
全栈程序员站长
2022/09/02
4650
相关推荐
Java基础系列(二十二):初识反射
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验