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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
EMR入门学习之Hue上创建工作流(十一)
本文将通过一个简单,并且具有典型代表的例子,描述如何使用EMR产品中的Hue组件创建工作流,并使该工作流每天定时执行。
披荆斩棘
2019/11/22
1.6K0
「EMR 开发指南」之 Hue 配置工作流
本文将通过一个简单,并且具有典型代表的例子,描述如何使用EMR产品中的Hue组件创建工作流,并使该工作流每天定时执行。
岳涛
2024/06/30
2641
「EMR 开发指南」之 Hue 配置工作流
EMR(弹性MapReduce)入门之组件Hue(十三)
Hue是一个开源的Apache Hadoop UI系统,由Cloudera Desktop演化而来,最后Cloudera公司将其贡献给Apache基金会的Hadoop社区,它是基于Python Web框架Django实现的。
小司机带你入门EMR
2020/02/14
2.1K0
腾讯云 EMR 常见问题100问 (持续更新)
Hadoop 目前是数据处理的标准工具,其核心组件包含了HDFS(分布式文件系统)、YARN(资源调度平台)、
benyukiwang
2019/07/02
5.6K1
基于hadoop生态圈的数据仓库实践 —— OLAP与数据可视化(六)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzy0623/article/details/52386016
用户1148526
2019/05/25
6910
数据开发治理平台Wedata之数仓建设实践
本案例基于腾讯云一站式开发治理平台Wedata、私有网络VPC、云数据库Mysql和弹性Mapreduce构建了全流程的离线数仓建设流程。通过模拟业务数据的导入,分层ETL和数据应用全过程,演示了如何在Wedata上进行高效的数据开发与治理。
张志刚
2022/05/07
2.9K0
EMR(弹性MapReduce)入门之初识EMR(一)
现在混迹技术圈的各位大佬,谁还没有听说过“大数据”呢?提起“大数据”不得不说就是Google的“三架马车”:GFS,MapReduce,Bigtable,分别代表着分布式文件系统、分布式计算、结构化存储系统。可以说这“三架马车”是大数据的基础。
小司机带你入门EMR
2020/01/16
11.6K5
EMR(弹性MapReduce)入门之初识EMR(一)
HAWQ取代传统数仓实践(五)——自动调度工作流(Oozie、Falcon)
        一旦数据仓库开始使用,就需要不断从源系统给数据仓库提供新数据。为了确保数据流的稳定,需要使用所在平台上可用的任务调度器来调度ETL定期执行。调度模块是ETL系统必不可少的组成部分,它不
用户1148526
2018/01/03
2.1K0
HAWQ取代传统数仓实践(五)——自动调度工作流(Oozie、Falcon)
Hadoop数据分析平台实战——180Oozie工作流使用介绍离线数据分析平台实战——180Oozie工作流使用介绍
离线数据分析平台实战——180Oozie工作流使用介绍 Oozie工作流介绍 Oozie的四大组件服务分别是: workflow, coordinator, bundle和sla。 其中sla是作为监控服务协议的一个组件, workflow定义oozie的基本工作流, coordinator定义定时(或者是根据其他资源指标)运行的workflow任务, bundle是将多个coordinator作为一个组件一起管理。 也就是说workflow是oozie中最基本的一个服务组件。 三大服务的的关系
Albert陈凯
2018/04/08
1.2K0
如何在HUE上通过oozie调用Hive SQL工作流
特别说明:该专栏文章均来源自微信公众号《大数据实战演练》,欢迎关注!
create17
2019/02/20
2.7K0
如何在HUE上通过oozie调用Hive SQL工作流
EMR入门学习之EMR初步介绍(一)
Elastic MapReduce(EMR)是腾讯云提供的云上 Hadoop 托管服务,提供了便捷的 Hadoop 集群部署、软件安装、配置修改、监控告警、弹性伸缩等功能,EMR部署在腾讯云平台(CVM)上,配合消息中间件、CDB等产品为企业提供了一套较为完善的大数据处理方案。如下图所示为EMR系统架构图:
披荆斩棘
2019/11/13
7.3K0
如何使用Hue创建Spark1和Spark2的Oozie工作流
使用Hue可以方便的通过界面制定Oozie的工作流,支持Hive、Pig、Spark、Java、Sqoop、MapReduce、Shell等等。Spark?那能不能支持Spark2的呢,接下来本文章就主要讲述如何使用Hue创建Spark1和Spark2的Oozie工作流。
Fayson
2018/03/29
5.1K1
如何使用Hue创建Spark1和Spark2的Oozie工作流
什么是Oozie?如何使用Oozie?蒟蒻博主带你快速上手Oozie!
本篇博客,博主为大家介绍的是Oozie,一种运行在hadoop平台上的工作流调度引擎。如果看完后有点收获,不妨给博主一个大大的赞|ू・ω・` )
大数据梦想家
2021/01/27
2.5K0
什么是Oozie?如何使用Oozie?蒟蒻博主带你快速上手Oozie!
Oozie分布式任务的工作流——脚本篇
继前一篇大体上翻译了Email的Action配置,本篇继续看一下Shell的相关配置。 Shell Action Shell Action可以执行Shell脚本命令,工作流会等到shell完全执行完毕后退出,再执行下一个节点。为了运行shell,必须配置job-tracker以及name-node,并且设置exec来执行shell. Shell既可以使用job-xml引用一个配置文件,也可以在shell action内直接配置。shell action中的配置会覆盖job-xml中的配置。 EL表达式
用户1154259
2018/01/17
1.1K0
基于Hadoop生态圈的数据仓库实践 —— ETL(三)
三、使用Oozie定期自动执行ETL 1. Oozie简介 (1)Oozie是什么 Oozie是一个管理Hadoop作业、可伸缩、可扩展、可靠的工作流调度系统,其工作流作业是由一系列动作构成的有向无环图(DAGs),协调器作业是按时间频率周期性触发的Oozie工作流作业。Oozie支持的作业类型有Java map-reduce、Streaming map-reduce、Pig、 Hive、Sqoop和Distcp,及其Java程序和shell脚本等特定的系统作业。 第一版Oozie是一个基于工作流引擎的服务器,通过执行Hadoop Map/Reduce和Pig作业的动作运行工作流作业。第二版Oozie是一个基于协调器引擎的服务器,按时间和数据触发工作流执行。它可以基于时间(如每小时执行一次)或数据可用性(如等待输入数据完成后再执行)连续运行工作流。第三版Oozie是一个基于Bundle引擎的服务器。它提供更高级别的抽象,批量处理一系列协调器应用。用户可以在bundle级别启动、停止、挂起、继续、重做协调器作业,这样可以更好地简化操作控制。 (2)为什么需要Oozie
用户1148526
2019/05/25
1.1K0
0462-如何在Hue中创建Shell Action工作流续
Fayson在前面的文章《Hue中使用Oozie创建Shell工作流在脚本中切换不同用户》,里面介绍了Shell Action的创建,在文中我们相应的Shell脚本是放在每个Oozie作业对应的WorkSpace的lib目录下。对于一些对于所有用于都公用的Shell脚本可能放在HDFS的公共目录下,那这时创建Shell Action需要注意些什么呢?本篇文章Fayson主要介绍在Hue中创建Shell Action指定工作空间外的Shell脚本。
Fayson
2018/12/17
9460
如何在HUE上通过oozie调用Spark工作流
访问ip:8888/about/#step2,点击下载Oozie Editor/Dashboard,可以下载应用程序示例。如下图所示:
create17
2019/03/12
2.8K0
oozie创建工作流,手动配置和使用H
工作流的执行命令参考博客:https://www.jianshu.com/p/6cb3a4b78556,也可以键入oozie help查看帮助
py3study
2020/01/06
7700
Hadoop的生态系统介绍
Hadoop分布式文件系统是Hadoop项目的两大核心之一,是针对谷歌文件系统(GoogleFileSystem,GFS)的开源实现。是Hadoop体系中数据存储管理的基础。它是一个高度容错的系统,能检测和应对硬件故障,用于在低成本的通用硬件上运行。HDFS简化了文件的一致性模型,通过流式数据访问,提供高吞吐量应用程序数据访问功能,适合带有大型数据集的应用程序。
全栈程序员站长
2022/08/31
1.2K0
Hadoop的生态系统介绍
Kettle构建Hadoop ETL实践(七):定期自动执行ETL作业
一旦数据仓库开始使用,就需要不断从源系统给数据仓库提供新数据。为了确保数据流的稳定,需要使用所在平台上可用的任务调度器来调度ETL定期执行。调度模块是ETL系统必不可少的组成部分,它不但是数据仓库的基本需求,也对项目的成功起着举足轻重的作用。
用户1148526
2020/10/26
6.6K0
Kettle构建Hadoop ETL实践(七):定期自动执行ETL作业
推荐阅读
相关推荐
EMR入门学习之Hue上创建工作流(十一)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验