首页 > 编程语言 >详解Java反射机制

详解Java反射机制

时间:2023-06-23 23:49:01浏览次数:44  
标签:反射 Java String 构造方法 详解 方法 Class

前言

反射(Reflection) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,并能直接操作程序的内部属性和方法。主要有两种方式:一种是“传统的”RTTI,它假定我们在编译时已经知道了所有的类型;另一种是“反射”机制,它允许我们在运行时发现和使用类的信息。

本篇就让我们深入了解下 Java 的反射技术,共同探究 java 程序的运行机制。

反射的概念和原理

反射的概念是由 Smith 在 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗地讲,一提到反射,我们就可以想到镜子。镜子可以明明白白地照出我是谁,还可以照出别人是谁。反映到程序中,反射就是用来让开发者知道这个类中有什么成员,以及别的类中有什么成员。

为什么要有反射

有人可能会疑惑,Java 已经有了封装为什么还要有反射呢?反射看起来会破坏封装性。甚至让私有变量都可以被外部访问到,使得类变得不那么安全了。

反射主要应用在以下几方面:

  1. 开发通用框架:像 Spring,为了保持通用性,通过配置文件来加载不同的对象,调用不同的方法。
  2. 动态代理:在面向切面编程中,需要拦截特定的方法,就会选择动态代理的方式,而动态代理的底层技术就是反射。
  3. 注解:注解本身只是起到一个标记符的作用,它需要利用发射机制,根据标记符去执行特定的行为。

反射 API

Java 类的成员包括以下三类:属性字段、构造函数、方法。反射的 API 也是与这几个成员相关:

Field 类:提供有关类的属性信息,以及对它的动态访问权限。它是一个封装反射类的属性的类。

Constructor 类:提供有关类的构造方法的信息,以及对它的动态访问权限。它是一个封装反射类的构造方法的类。
Method 类:提供关于类的方法的信息,包括抽象方法。它是用来封装反射类方法的一个类。

Class 类:表示正在运行的 Java 应用程序中的类的实例。

Object 类:Object 是所有 Java 类的父类。所有对象都默认实现了 Object 类的方法。

接下来,我们通过一个典型的例子来学习反射。先做准备工作,新建 com.test.reflection 包,在此包中新建一个 Student 类:

package com.test.reflection;

public class Student {

    private String studentName;
    public int studentAge;

    public Student() {
    }

    private Student(String studentName) {
        this.studentName = studentName;
    }

    public void setStudentAge(int studentAge) {
        this.studentAge = studentAge;
    }

    private String show(String message) {
        System.out.println("show: " + studentName + "," + studentAge + "," + message);
        return "testReturnValue";
    }
}

图中可以看出,Student 类中有两个字段、两个构造方法、两个函数,且都是一个私有,一个公有。由此可知,这个测试类基本涵盖了我们平时常用的所有类成员。

获取Class对象的方法

1)通过类名创建Class对象

Class clz = Class.forName("java.lang.String");

2)通过类的实例对象的getClass()方法获取Class对象

String s = new String();
Class clz = s.getClass();

3)通过类的.class属性获取Class对象

Class clz = int.class;

实践

让我们实际写个代码例子:

// 1.通过字符串获取Class对象,这个字符串必须带上完整路径名
Class studentClass = Class.forName("com.test.reflection.Student");
// 2.获取声明的构造方法,传入所需参数的类名,如果有多个参数,用','连接即可
Constructor studentConstructor = studentClass.getDeclaredConstructor(String.class);
// 如果是私有的构造方法,需要调用下面这一行代码使其可使用,公有的构造方法则不需要下面这一行代码
studentConstructor.setAccessible(true);
// 使用构造方法的newInstance方法创建对象,传入构造方法所需参数,如果有多个参数,用','连接即可
Object student = studentConstructor.newInstance("NameA");
// 3.获取声明的字段,传入字段名
Field studentAgeField = studentClass.getDeclaredField("studentAge");
// 如果是私有的字段,需要调用下面这一行代码使其可使用,公有的字段则不需要下面这一行代码
// studentAgeField.setAccessible(true);
// 使用字段的set方法设置字段值,传入此对象以及参数值
studentAgeField.set(student,10);
// 4.获取声明的函数,传入所需参数的类名,如果有多个参数,用','连接即可
Method studentShowMethod = studentClass.getDeclaredMethod("show",String.class);
// 如果是私有的函数,需要调用下面这一行代码使其可使用,公有的函数则不需要下面这一行代码
studentShowMethod.setAccessible(true);
// 使用函数的invoke方法调用此函数,传入此对象以及函数所需参数,如果有多个参数,用','连接即可。函数会返回一个Object对象,使用强制类型转换转成实际类型即可
Object result = studentShowMethod.invoke(student,"message");
System.out.println("result: " + result);

以上代码逻辑梳理如下:

  • 先用第一种全路径获取 Class 的方法获取到了 Student 的 Class 对象
  • 然后反射调用它的私有构造方法 private Student(String studentName),构建出 newInstance
  • 再将其公有字段 studentAge 设置为 10
  • 最后反射调用其私有方法 show,传入参数 “message”,并打印出这个方法的返回值。

其中,setAccessible 函数用于动态获取访问权限,Constructor、Field、Method 都提供了此方法,让我们得以访问类中的私有成员。

反射的优缺点

  • 优点:自由,使用灵活,不受类的访问权限限制。可以根据指定类名、方法名来实现方法调用,非常适合实现业务的灵活配置。
  • 缺点
  1. 正因为反射不受类的访问权限限制,其安全性低,很大部分的java安全问题都是反射导致的。
  2. 相对于正常的对象的访问调用,反射因为存在类和方法的实例化过程,性能也相对较低
  3. 破坏java类封装性,类的信息隐藏性和边界被破坏

本文由mdnice多平台发布

标签:反射,Java,String,构造方法,详解,方法,Class
From: https://www.cnblogs.com/GentleJim/p/17500484.html

相关文章

  • 无处不在 | 亚马逊云科技的 Java 生态
    Java自诞生以来就一直是热门的编程语言。得益于丰富的生态以及完善维护的包和框架,Java拥有着庞大的开发者社区。这个1995年诞生的计算机语言,以“一次编写,到处运行”的跨平台特性以及面向对象、泛型编程等现代语言的特性迅速成为了企业级应用乃至移动应用开发的首选。亚马逊......
  • JAVA笔记
    三元运算符x?y:z如果x==ture,则结果为y,否则结果为zJava中的三元运算符x?y:z可以简化一些if/else语句的书写,其中x是一个布尔表达式,如果x为true,则返回y,否则返回z。该运算符也称为条件运算符或三目运算符,因为它由三个操作数组成。例如,下面的代码使用if/els......
  • java编程开发之若依vue框架 --- 后台开发
    分页实现前端基于element封装的分页组件 pagination(opensnewwindow)后端基于mybatis的轻量级分页插件pageHelper(opensnewwindow)#前端调用实现1、前端定义分页流程  #后台逻辑实现@PostMapping("/list")//定义/list接口,用于查询出列表@ResponseBody//返......
  • java编程开发之若依vue --- 部署
      部署的大致步骤0.配置环境,jdk下载安装配置环境变量,Mysql下一步就好记住用户名和密码,Redis下载win版本运行即可,Maven下载配置环境变量修改本地库存放位置,Node下一步就好设置下淘宝的镜像源。JDK>=1.8(推荐1.8版本)Mysql>=5.7.0(推荐5.7版本)Redis>=3.0Maven>......
  • DVWA靶场之SQL注入通关详解
    原理SQL注入通过将恶意的SQL代码插入到应用程序后台的SQL语句中,以获取未授权的访问权限或者窃取应用程序中的敏感信息。通常,SQL注入攻击的目标是Web应用程序,因为Web应用程序通常需要与数据库进行交互,并且大多数Web应用程序使用的是SQL语言。存在原因Web应用程序没有对用户输入......
  • Java 程序控制结构
    Java程序控制结构1.顺序结构即按照从上到下依次执行到main()方法结束2.分支结构单分支(if)双分支(if-else)多分支(ifelseif...)嵌套分支(分支里面嵌套分支,建议不超过3层)Switch分支switch(表达式)case常量1:...;break;...............................
  • JAVA面向对象程序设计_PTA题目集07-11总结分析
    JAVA面向对象程序设计_PTA题目集07-11总结分析前言:天将降大任于是人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为。所以动心忍性,增益其所不能。随堂检测在最末浅析。 题目集七:知识点:类间设计,类的设计。题量:一题,菜单计价五。难度:八个满分。 题目集八:知识点:类......
  • 有关java的博客-3
    一、前言本次博客主是针对java学习第三阶段中的第6-8次PTA题目(成绩计算系列)的总结性博客,第三阶段的作业难度与第一阶段和第二阶段想必有所提高,对java的知识点考察主要集中在类的设计,正则表达式的运用,类的继承,多态,抽象类与接口。二、设计与分析1.课程成绩统计程序-11)类图 2......
  • 指针详解
    一、指针运算给一个指针变量+1,通常情况下不是给指针本身+1,而是”迈一步“,步长根据指针的类型来确定。intmain(){ chara=1; intb=1; intarr[10]={0}; char*pa=&a; int*pb=&b; int(*parr)[10]=&arr; printf("%p\n",pa); printf("%p\n",pa+1);//......
  • 【电商平台京东api接口系列】api获取商品详情Java请求返回值说明
    前言京东商品详情API接口的作用是获取京东平台上某个商品的详细信息,包括商品标题、价格、图片、规格、参数、店铺信息等。开发者可以通过该接口获取到商品的原始数据,方便进行数据分析、价格比较、爬取等操作。通过该接口获取到的商品详情数据可以结合其他数据进行深度挖掘,例如可以......