Java反射详解

VTK 显示大量点云数据及交互(点云拾取、着色、测量等)功能 VTK (Visualization Toolkit) 是一个强大的开源可视化库,非常适合处理点云数据。下面将介绍如何使用 VTK 显示大量点云数据,并实现点云拾取、着色、测量等功能。 阅读详情

转载注明出处:http://blog.youkuaiyun.com/xiaohanluo/article/details/52034127

1. 简介

       Java在编译时候就必须知道所引用的类所在地方,但是在实际编程中,在某些场合,可能需要引用一个并不在编译空间的类,这个时候常规方法就很难实现了。在Java中,Class配合反射能够很好的解决这种场景。Java里面的反射可以帮助我们在运行程序时候加载、使用编译期间完全未知的class,简单来说就是Java可以加载一个运行时候才得知名称的class,获得其完整的构造,并生成实例化对象,对其成员变量赋值,调用其方法等等。

       在具体的研发中,通过反射获取类的实例,大大提高系统的灵活性和扩展性,同时由于反射的性能较低,而且它极大的破坏了类的封装性(通过反射获取类的私有方法和属性),在大部分场景下并不适合使用反射,但是在大型的一些框架中,会大范围使用反射来帮助架构完善一些功能。

       上面说了一些简介,接下来直接就看看怎么使用反射来帮助我们获取class中的一些属性和方法吧。

2. 说明

反射机制中会用到一些类,在了解反射是如何使用之前,先介绍一下这些类。

类说明
Class在反射中表示内存中的一个Java类,Class可以代表的实例类型包括,类和接口、基本数据类型、数组
ObjectJava中所有类的超类
Constructor封装了类的构造函数的属性信息,包括访问权限和动态调用信息
Field提供类或接口的成员变量属性信息,包括访问权限和动态修改
Method提供类或接口的方法属性信息,包括访问权限和动态调用信息
Modifier封装了修饰属性, public、protected、static、final、synchronized、abstract等

注:Class本身就是一个类,Class就是这个类的名称(注意首字母是大写);public class Demo {},这里的class是作为关键字,来表明Demo是一个类

3. 获取属性

通过反射可以获取类的多种属性,并对其进行一些操作,例如获取其中的某个方法并调用。先定义一个基础的类,然后用反射获取这个类的一些信息吧。

接口,仅仅名声了一个eat()方法

public interface IHumanAction {
    void eat();
}

具体的类,注意类各个方法的修饰属性。

public class Human implements IHumanAction {
    private int age;
    public String name;

    public Human() {

    }

    Human(String name) {
        this.name = name;
    }

    protected Human(int age) {
        this.age = age;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    protected void eatApple() {
        System.out.println("eat apple");
    }

    void playGame() {

    }

    @Override
    public void eat() {
        System.out.println(this.name + " performs eat");
    }

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

3.1 基类或者接口

       最基本的,可以通过反射,来获取一个类的基类或者实现的接口,使用getSuperclass()或者该类的基类,使用getInterfaces()来获取该类实现的接口。直接看一下例子。

try {
    Class clz = null;
    clz = Class.forName("com.wang.demo.reflect.Human");
    if(clz != null) {
        Class superClass = clz.getSuperclass();
        System.out.println("该类的父类:");
        System.out.println(superClass.getName());

        System.out.println("该类实现的接口:");
        Class[] interfaces = clz.getInterfaces();
        for (Class clazz : interfaces) {
            System.out.println(clazz.getName());
        }
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

运行结果如下图。
图-1 获取基类和接口
       因为在java中,类是单一继承,而接口可以实现多个,所以getSuperclass()方法返回的是个Class对象,而getInterfaces()返回的是一个Class数组。

3.2 构造函数

       获取基类和接口的方法比较单一,是直接返回了类的一些基本属性,而在获取构造函数、方法、成员变量属性时候,不同的方法是返回不同的结果。

先看获取构造函数的例子。

try {
    Class clz = null;
    clz = Class.forName("com.wang.demo.reflect.Human");

    if(clz != null) {
        int modify;
        System.out.println("该类的构造函数(getConstructors()):");

        Constructor[] cons = clz.getConstructors();
        for(Constructor constructor : cons) {
            modify = constructor.getModifiers();
            System.out.println(Modifier.toString(modify) + " " + constructor.getName());
        }

        System.out.println("\n该类的构造函数(getDeclaredConstructors()):");
        Constructor[] cons2 = clz.getDeclaredConstructors();
        for(Constructor constructor : cons2) {
            modify = constructor.getModifiers();
            System.out.println(Modifier.toString(modify) + " " + constructor.getName());
        }

        System.out.println("\n根据参数获取构造函数:");
        Constructor cons3 = clz.getDeclaredConstructor(int.class);
        if(cons3 != null) {
            System.out.println(Modifier.toString(cons3.getModifiers()) + " " + cons3.getName());
        }

        System.out.println("\n根据参数获取构造函数:");
        Constructor cons4 = clz.getConstructor(int.class);
        if(cons3 != null) {
            System.out.println(Modifier.toString(cons4.getModifiers()) + " " + cons4.getName());
        }
    }

} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

运行结果如下图。
图-2 获取构造函数

       在我们定义的Human类中,有四个构造函数,两个public属性的,一个default属性,一个protected属性。

       从运行结果中可以看见,getConstuctors()得到了两个构造函数,都是public属性的,getDelaredConstructors()得到了四个构造函数,获取了Human类中的所有构造函数,跟构造函数的属性无关。getDelaredConstructor(params)根据构造函数的参数类型,获取了相匹配的构造函数,而同样的参数getConstuctor(params)抛出了异常,这是因为getConstuctor(params)根据参数去匹配所有的public属性的构造函数,而getDelaredConstructor(params)是根据参数去匹配所有的构造函数。

总体来说,四种获取构造函数的方法的区别如下:

  • getConstuctors(),获取的构造函数全部是public属性的。
  • getConstuctor(Class … params),根据参数,从所有public属性的构造函数中获取相关构造函数
  • getDelaredConstructors(),获取所有的构造函数
  • getDelaredConstructor(Class … params),根据参数,从所有的构造函数中获取相关构造函数

3.3 方法

在Java中,一般通过getMethods()或者getDeclaredMethod()方法来获取类中定义的方法。直接看一下这二个方法执行的例子。

例子代码:

try {
    Class clz = null;
    clz = Class.forName("com.wang.demo.reflect.Human");

    if(clz != null) {
        System.out.println("获取该类的方法(getMethods()):");
        Method[] methods1 = clz.getMethods();
        for(Method method : methods1) {
            System.out.println(Modifier.toString(method.getModifiers()) + " " +
                    method.getReturnType() + " " +
                    method.getName());
        }

        System.out.println("\n获取该类的方法(getDeclaredMethods())");
        Method[] methods2 = clz.getDeclaredMethods();
        for(Method method : methods2) {
            System.out.println(Modifier.toString(method.getModifiers()) + " " +
                    method.getReturnType() + " " +
                    method.getName());
        }
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

运行结果:
图-3 获取方法
       这两个方法获取的结果差别还是比较大的,可以看见,getMethods()返回的都是类中public属性的方法,不止是本身声明过的public属性的方法,也包括基类中声明的public属性的方法。而getDeclaredMethods()返回的则是在类自身声明的所有方法,包括复写的方法。

       事实上,通过反射获取类中的方法还有getMethod(name,params)和getDeclaredMethod(name, params),这两个方法主要区别在于通过参数筛选的范围不同。

四种方法的区别:
- getMethods()返回类中所有的public属性的方法,包括从基类继承的public方法。
- getDeclaredMethods()返回类本身声明的方法,包括复写的方法,不包括从基类继承的方法
- getMethod(name,params)根据参数从getMethods()返回的结果中筛选
- getDeclaredMethod(name, params)根据参数从getDeclaredMethods()返回的结果中筛选

3.4 成员变量

       成员变量获取和上面类似,主要方法有getFields()、getDeclaredFields()、getMethod(name, params)、getDeclaredMethod(name, params)四种方法。

看一下使用的例子吧。

try {
    Class clz = null;
    clz = Class.forName("com.wang.demo.reflect.Human");

    if(clz != null) {
        System.out.println("获取该类的成员变量(getFields()):");
        Field[] fields1 = clz.getFields();
        for(Field field : fields1) {
            System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getName());
        }

        System.out.println("\n获取该类的成员变量(getDeclaredFields()):");
        Field[] fields2 = clz.getDeclaredFields();
        for(Field field : fields2) {
            System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getName());
        }

    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

运行结果:
图-4 获取成员变量

       可以看到getFields()方法只返回了public属性的成员变量,而getDeclaredFields()方法返回了所有的成员变量。至于getMethod(name, params)和getDeclaredMethod(name, params)都是在相应的范围获取成员变量。

四个方法的具体区别:
- getFields()获取类的所有public属性的成员变量
- getDeclaredFields()获取类的所有成员变量
- getMethod(name, params)根据参数在getFields()获取的成员变量中进行筛选
- getDeclaredMethod(name, params)根据参数在getDeclaredFields()获取的成员变量中进行筛选

3.5 调用&赋值

       上面说明了获取类的一些属性的方法,包括构造函数、方法和成员变量。在获取这个属性之后我们可以调用构造函数实例化对象,调用其中的方法,给成员变量赋值。

直接看代码。

try {
    Class clz = null;
    clz = Class.forName("com.wang.demo.reflect.Human");

    if(clz != null) {
        Constructor constructor = clz.getDeclaredConstructor(int.class);
        Human human = (Human)constructor.newInstance(1);
        System.out.println(human.toString());

        Method method = clz.getMethod("setName", String.class);
        method.invoke(human, "John");
        System.out.println(human.toString());

        Field field = clz.getDeclaredField("age");
        field.setAccessible(true);
        field.set(human, 12);
        System.out.println(human.toString());
    }
} catch (Exception e) {
    e.printStackTrace();
}

运行结果:
图-5 运行结果
       代码中,我先利用反射获取构造函数Human(int age),然后实例化一个Human对象,这个时候打印出Human信息,由于在实例化时候设置了age为1,打印出来结果name是没有值得;然后通过反射获取setName(String name)方法,并调用设置name为Jhon,输出时候可以看见age为1,name为Jhon;最后通过反射获取到Human的age成员变量,并将值设置为12,输出时候可以看见age已经改变为12了。

4. 总结

       反射的使用非常简单,在一般场景下也很少用到。但是作为Java中的一个比较重要的辅助机制,还是需要了解。由于反射在获取一些属性时候异常情况比较多,一定需要慎重使用,而且反射性能比较差,在普通场景下,并不建议大量使用反射。

MATLAB使用贝叶斯网络bnt工具箱:使用手册详解 MATLAB使用贝叶斯bnt网络工具箱:使用手册详解 阅读详情

相关推荐

计算机网络Wireshark实验(西安交通大学)

实验名称 计算机网络Wireshark实验 实验日期 2021 年 5 月 17 日 实验地点 XJTU

沉鱼叶的博客 1817

Java中的反射

java中的反射 一、主要使用的类 1.Class类:代表类的定义 Class对象的获取方式 1.Class clz = Class.forName(“类的完全限定名”); 2.Class clz =类名.class ; 3.Class clz = 对象.getClass( ); 常用的方法 forName(String className)注意参数是全类名(包名+类名) newInstance( ) 创建类的实例(对象) getName( ) 获得类的完整路径名字 getSimple

qq_41713361的博客 168

LLM and Embedding区别

LLM(大语言模型)和 Embedding(嵌入)是自然语言处理(NLP)中的两个核心概念,它们的核心区别在于。Embedding 计算向量。

u010674101的专栏 1875

Java基础之-反射

0.什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 1.获取Class对象反射的第一步,就是去获取Class对象,而我们获取Class对象有三种方法,下面一一说明。1.1方法一Class<?> clz = User.clas

_StriveG的专栏 1035

STM32+CubeMX实战:5步搞定LWIP HTTP服务器搭建(附常见编译错误解决)

本文详细介绍了基于STM32和CubeMX平台,快速搭建LWIP HTTP服务器的5步实战指南。内容涵盖从项目初始化、LWIP深度配置到解决经典的`HTTPD_FSDATA_FILE`编译错误,并分享了使用VSCode进行高效开发的工作流,旨在帮助嵌入式开发者快速实现网络功能并规避常见陷阱。

weixin_29192365的博客 574

latex写论文(TeXstudio工具)

目录前言IEEE模板模板免费分享参考文献写作方法我的.tex文件代码 前言 学校老师要求我们以IEEE顶级会议格式与标准写报告,于是过程虽然麻烦点,但是效果还是不错了,下面先展示一下自己写完的效果。 IEEE模板 我是在 Overleaf 上注册了个账号下载了模板,里面有各种会议论文的写作模板,这个注册还挺麻烦,要外网注册,国内邮箱都不行。进行后点菜单,菜单里有下载源码。 https://cn.overleaf.com/project/5fe5b082dff088649fc67106 模板免费分享 已

小样yx的博客 6753

java——如何通过class调用该类的方法并获得返回值?(反射)

demo: public class T{ public static void main(String[] args) throws Exception{ //获得Person的Class对象 Class<?> cls = Person.class;//Class.forName("testJavaSE.Person");...

dengyunhui1210的博客 1870

Java 基础进阶篇(十七):反射概述及获取对象的方式

一、反射概述 二、反射获取类对象 三、反射获取构造器对象 四、反射获取成员变量对象 五、反射获取方法对象 六、 反射的作用 6.1 绕过编译阶段为集合添加数据 6.2 通用框架的底层原理

秀岩的博客 4451

从零配置到批量处理:FaceFusion 3.1完整使用指南(含hififace_256模型测试)

本文详细介绍了FaceFusion 3.1的完整使用指南,包括环境配置、模型选择(特别是hififace_256模型的深度测试)以及批量处理技巧。通过AI驱动的脸部替换技术,帮助用户高效实现高质量的面部处理,适用于影视制作、广告设计等多种场景。

weixin_29056865的博客 655

【Codex】Codex安装+DeepSeek API接入;无需登录,手把手带你使用codex

好多人使用codex时都卡在验证码登录那一步,今天就来介绍一种方法,不需要登录ChatGPT的账号,自然也就不需要手机验证码了;接入DeepSeek的api,一样可以丝滑使用codex;记录从零开始安装使用codex以及DeepSeek API接入的整个过程。不需要登录openAI;

AnChenliang_1002的博客 3542

反射

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。在运行时,可以直接得到这个类的构造器对象:Constructor。在运行时,可以直接得到这个类的成员变量对象:Field。在运行时,可以直接得到这个类的成员方法对象:Method。这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

cndiafcbsfiuv的博客 281

Obsidian与RAG:知识管理的未来之战

摘要: 本文对比了传统RAG、Obsidian和llm-wiki-skill三种知识管理方案。传统RAG依赖查询时临时检索,知识无法积累;Obsidian需人工整理,成本高但结构化强;llm-wiki-skill通过AI在摄入时自动编译知识为结构化Wiki,实现持续增值。核心差异在于知识处理时机——llm-wiki-skill将"查询时检索"转变为"摄入时编译",通过三层Markdown结构(sources/concepts/entities)和自动双向链接构建可进化

ZhangJiqun&191cm&85kg 622

Java 反射

反射(reflection)是 Java 中的一项特性,它允许程序在运行时查询和操作类的信息。即,在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性。获取到方法和属性后,就可以对其进行修改。这种动态获取信息以及动态调用对象方法的功能也就是Java的反射机制

2301_76161469的博客 8777

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java 反射 详解

java 反射 详解

T_Y_F_的博客 1130

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java 反射详解和使用

反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性;

m0_58375976的博客 8325

【Java】反射详解

本文详细介绍了Java反射机制,主要包括以下内容:1. 反射概述,解释了反射的概念、应用场景及优缺点;2. 获取Class对象的三种方式及类信息获取方法;3. 构造方法反射操作,包括获取构造方法、创建对象实例等。文章通过代码示例演示了如何使用反射动态获取类信息、操作构造方法,适用于框架开发、动态代理等场景,但需注意反射的性能开销和封装性问题。

小昭的博客 1683

JAVA【反射】详解

JAVA反射机制是在运行时,对于任意一个类,都能够知道这个类的所有方法和属性;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Locus的博客 917

JAVA反射调用详解

JAVA反射调用的确是一种很神奇的机制,在项目中使用后恋恋不忘,现将其好好整理一下。 参考: 学习JAVA应该如何理解反射?知乎 https://www.zhihu.com/question/24304289 全面细致讲解反射机制系列 http://www.365yg.com/item/6414118008049893889/?iid=9697930986&app=news_artic

Aka丶的博客 8195

详解Java反射

Java反射机制是静态类型语言的动态特性,允许程序在运行时获取类信息、调用方法和修改属性。摘要如下: 反射基础:Java作为静态语言,类型检查在编译时完成,而反射打破了这一限制,实现动态操作。 获取Class对象的三种方式: 类名.class(编译时已知) 对象.getClass() Class.forName("类名")(最灵活) 核心操作: 实例化对象(包括处理私有构造方法) 动态调用方法 修改属性(包括私有成员) 特殊场景处理: 单例模式实例化(如Runtime类) 内部类反射写法

Python1111111的博客 1153

java反射&python反射

作为一只主学java,次学python的猿,反射的梗,怎能不知道 一、反射是什么: 维基百科上给出的定义:在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。 以我浅薄的编程思想理解的反射: 反射可以让我们在不打开程序文件的情况下,清楚的知道该程序的内部结构...

远处 1475

详解 Java 反射

反射,反射,程序员的快乐!

Alpinist Wang 884

Java反射机制详解

在Java中,反射(Reflection)是指在运行时检查、访问和修改类、接口、字段和方法等程序结构的能力。Java反射机制允许程序在运行时获取任何类的内部信息,并且能够直接操作任意对象的内部属性及方法。简单来说,反射就是把Java类中的各种成分(构造方法、成员变量、方法等)映射成相应的Java类,并在运行时动态地获取类信息以及操作类的对象。Java的反射机制使得我们可以在程序运行时:Java反射API主要由以下几个类组成,它们都位于包中:下面是一个简单的反射示例,展示了如何获取类的信息并调用方法: 执行结

yk_dflkg的博客 1180
上一篇: AsyncTask 第三篇源代码篇
下一篇: 带你从源代码详细分析View的绘制过程
王三的猫阿德
王三的猫阿德 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄15年 179粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值