第九周学习笔记DAY.1-反射

devtools/2024/9/25 7:24:17/

在计算机学科中,反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。通过Java的反射机制,程序员可以更深入地控制程序的运行过程,如在程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程。理解反射机制是学习Spring框架的基础。

一、反射简介

(1)Java的反射机制是一种动态获取信息以及动态调用对象的方法的功能。

(2)具体来说,在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

(3)通过Java反射机制,就可以在程序中访问已经装载到JVM中的Java对象的各种描述,能够访问、检测和修改描述Java对象本身信息。

(4)Java在java.lang.reflect包中提供了对该功能的支持。

二、反射与Class类

(1)反射与Class类息息相关。Class对象封装了它所代表的类的描述信息,通过调用Class对象的各种方法,就可以获取到Class对象所代表的类的主要描述信息。

(2)获取目标类的Class对象,有以下3种方法可以实现:

  1. 使用Object类的getClass()方法

  2. 使用Class类的forName(String url)方法,用目标类的完整路径作为参数

  3. 使用目标类的class属性

在com.cxyzxc.reflect包中定义Person类

package com.cxyzxc.www.entity;public class Person {//公共属性public String name;//私有属性private int age;//无参构造public Person() {this.name = "张三";this.age = 18;}//有参构造public Person(String name, int age) {this.name = name;this.age = age;}//私有有参构造private Person(String name) {this.name = name;this.age = age;}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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}//无参方法public void eat(){System.out.println("今天吃了1顿大餐");}//带参方法public void eat(int num){System.out.println("今天吃了"+num+"顿大餐");}//私有方法private void sleep(){System.out.println("非常舒服的睡了一觉");}
}

获取Class类对象

package com.cxyzxc.www.reflect;import com.cxyzxc.www.entity.Person;public class Demo01GetClass {public static void main(String[] args) throws ClassNotFoundException {//获取Class对象//方法一:使用Class.forName()方法Class personClass1 =Class.forName("com.cxyzxc.www.entity.Person");//方法二:使用类的class属性Class personClass2 = Person.class;//方法三:使用Object类中的getClass()方法Person person = new Person();Class personClass3 = person.getClass();//使用Class.forName()方法和使用类的class属性获取的Class对象是同一个对象System.out.println("personClass1和personClass2是同一个对象:"+(personClass1==personClass2));//true//使用类的class属性和使用Object类中的getClass()方法获取的Class对象是同一个对象System.out.println("personClass1和personClass2是同一个对象:"+(personClass2==personClass3));//true}
}

运行结果

(3)Class对象常用方法如下表所示:

方法功能描述
Package getPackage()获得类所在的包路径
String getName()获得类(或接口、数组等)的名称
Class getSuperclass()获得该类的父类的Class对象
Class getInterfaces()获得该类实现的所有接口
Constructor[] getConstructors()获得该类的public修饰的构造方法,按声明顺序返回
Constructor getConstructor(Class<?>...ParameterType)获得该类的public修饰的特定参数列表的构造方法
Constructor[] getDeclaredConstructors()获得该类的所有构造方法
Constructor getDeclaredConstructors(Class<?>...ParameterType)获得该类的特定参数列表的构造方法
Method[] getMethods()获得该类的所有public修饰的方法
Method getMethod(String name,Class<?>...ParameterType)获得该类的public修饰的特定参数列表的方法
Method[] getDeclaredMethods()获得该类的所有方法,包含private修饰的方法,按声明顺序返回
Method[] getDeclaredMethods(String name,Class<?>...ParameterType)获得该类的特定参数列表的方法,包括private修饰的方法
Field[] getFields()获得该类的所有public修饰的成员变量
Field getField(String name)获得该类的public修饰的特定名称的成员变量
Field[] getDeclaredFields()获得该类的所有成员变量,包括private修饰的成员变量,按声明顺序返回
Field getDeclaredField(String name)获得特定名称的成员变量

三、反射访问构造方法

使用Class对象的如下方法,将返回Constructor类型对象或数组,每个Constructor代表一个构造方法。

方法功能描述
Constructor getConstructor()返回Constructor,匹配public修饰的不带参的构造方法
Constructor[] getConstructors()返回Constructor数组,匹配public修饰的所有构造方法
Constructor getConstructor(Class<?>...ParameterType)返回Constructor,匹配和参数列表相同的构造方法
Constructor[] getConstructors(Class<?>...ParameterType)返回Constructor数组,匹配和参数列表相同的构造方法
Constructor getDeclaredConstructor()返回Constructor,匹配包括private修饰的不带参的构造方法
Constructor[] getDeclaredConstructors()返回Constructor数组,匹配包括private修饰的构造方法
Constructor getDeclaredConstructor(Class<?>...parameterTypes)返回Constructor,匹配包括private修饰的和参数列表相同的构造方法
Constructor[] getDeclaredConstructors(Class<?>...parameterTypes)返回Constructor数组,匹配包括private修饰的和与参数列表想用的构造方法

其中,带有Class<?>...parameterType字样的方法代表构造方法的参数列表,实际运用时需要指定具体的类型。

Constructor类常用方法如下所示:

方法功能描述
boolean isVarargs()查看该构造方法是否带有可变数量的参数
Class[] getParameterTypes()获得该构造方法的各个参数的类型
Class[] getExceptionTypes()获得该构造方法可能抛出的异常类型
Object newInstance(Object...initargs)通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数,则表示采用默认无参数的构造方法
void setAccessible(boolean flag)如果该构造方法的权限为private,默认不允许通过反射利用newInstance(Object...iniargs)方法创建对象。如果先执行该方法,并将入口参数设为true,则允许创建
int getModifiers()返回构造方法所用修饰符的整数

使用反射访问Person类的构造方法

package com.cxyzxc.www.reflect;import com.cxyzxc.www.entity.Person;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Demo02GetConstructors {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//获取Class对象Class<Person> personClass1 = Person.class;System.out.println("--------------输出所有public修饰的构造方法--------------");//获得所有public修饰的构造方法Constructor[] constructors1 = personClass1.getConstructors();//遍历所有的构造方法for(Constructor constructor:constructors1){//输出构造方法对象System.out.println("构造方法:"+constructor);//获取构造方法的参数列表Class[] types = constructor.getParameterTypes();//遍历当前构造方法的参数列表for(int i = 0 ;i<types.length;i++){System.out.println("\t参数"+(i+1)+"类型:"+types[i]);}}System.out.println("--------------输出所有构造方法--------------");//获取所有构造方法Constructor[] constructors2 =personClass1.getDeclaredConstructors();//遍历输出所有Construct对象for (Constructor constructor:constructors2){//输出构造方法对象System.out.println("构造方法:"+constructor);//输出构造方法修饰符System.out.println("\t构造方法修饰符:"+(constructor.getModifiers()==1?"public":"private"));//获取构造方法的参数列表Class[] types = constructor.getParameterTypes();//遍历当前构造方法的参数列表for(int i = 0 ;i<types.length;i++){System.out.println("\t参数"+(i+1)+"类型:"+types[i]);}}System.out.println("--------------访问特定的构造方法--------------");System.out.println("-------无参构造方法-------");//获取无参构造方法Constructor constructor1 =personClass1.getConstructor();//通过无参构造方法创建Person对象Person person1=(Person) constructor1.newInstance();System.out.println(person1);System.out.println("-------有参构造方法-------");//获取有参构造方法Constructor constructor2 =personClass1.getConstructor(String.class,int.class);//通过有参构造方法创建对象Person person2=(Person)constructor2.newInstance("王五",25);System.out.println(person2);}
}

运行结果

四、反射访问成员变量

使用Class对象的如下方法,将返回Field型对象或数组。Field对象代表一个成员变量,利用Field对象可以访问和操纵相应的成员变量。

方法功能描述
getFields()获得所有的public修饰的成员变量
getFields(String name)获得指定名称的public修饰的成员变量
getDeclareFields()获得所有的成员变量,包括private修饰的成员变量
getDeclaredField(String name)获得指定名称的成员变量,包括private修饰的成员变量

Field类的常用方法

方法功能描述
String getName()返回该成员变量的名称
Class getType()返回表示该成员变量的类型的Class对象
Object get(Object obj)返回指定对象中成员变量的值
void set(Object obj,Object value)设置对象obj中成员变量的值为value
int getInt(Object obj)返回指定对象obj中类型为int的成员变量的值
void setInt(Object obj,int value)设置对象obj中类型为int的成员变量的值为value
float getFloat(Object obj)返回指定对象obj中类型为float的成员变量的值
setFloat(Object obj,float value)设置对象obj中类型为float的成员变量的值为value
boolean getBoolean(Object obj)返回指定对象obj中类型为boolean的成员变量的值
setBoolean(Object obj,boolean value)设置对象obj中类型为boolean的成员变量的值为value
getAccessible(boolean flag)设置是否允许直接访问private等私有权限的成员变量
getModifiers()返回成员变量所用修饰符的整数

反射访问Person送类的成员变量

com.cxyzxc.www.entity.Person");//获取有参构造方法Constructor constructor1 =personClass1.getConstructor(String.class,int.class);//通过有参构造方法创建对象Person person1= (Person) constructor1.newInstance("张三",28);System.out.println("-------------------遍历所有public修饰的属性-------------------");//获取所有public修饰的成员变量Field[] publicFields1 =personClass1.getFields();//遍历所有public修饰的属性for (Field pubField:publicFields1) {System.out.println("成员变量名称:"+pubField.getName());System.out.println("成员变量类型:"+pubField.getType());//获取成员变量的值if(pubField.getType().equals(String.class)){System.out.println("成员变量值:"+pubField.get(person1));}else if(pubField.getType().equals(int.class)){System.out.println("成员变量值:"+pubField.getInt(person1));}}System.out.println("-------------------遍历所有属性-------------------");Field[] fields = personClass1.getDeclaredFields();for (Field field:fields){System.out.println("成员变量名称:"+field.getName());System.out.println("成员变量类型:"+field.getType());System.out.println("成员变量修饰:"+(field.getModifiers()==1?"public":"private"));//获取成员变量值if(field.getType().equals(String.class)){System.out.println("成员变量值:"+field.get(person1));}else if(field.getType().equals(int.class)){//如果是私有的成员变量if(field.getModifiers()== Modifier.PRIVATE){//设置可以访问。不然会抛出IllegalAccess Exceptionfield.setAccessible(true);}System.out.println("成员变量值:"+field.getInt(person1));}}System.out.println("-------------------访问特定的成员变量-------------------");//获取姓名属性Field field1 = personClass1.getField("name");//修改姓名属性值field1.set(person1,"李二狗");System.out.println(person1);//反射获取私有成员变量,会抛出异常
//        Field field2 =personClass1.getFields("age");
//        System.out.println(field2);//暴力获取私有字段Field field2 = personClass1.getDeclaredField("age");field2.setAccessible(true);field2.set(person1,30);System.out.println(person1);}
}

运行结果

五、反射访问成员方法

使用Class对象的如下方法,将返回Method型对象或数组,Method对象代表一个方法。

方法功能描述
getMethods()获得所有public修饰的方法,包括父类的方法
getMethod(String name,Class<?>...parametertTypes)获得public修饰的特定名称和参数列表的方法
getDeclaredMethods()获得所有方法,包括private修饰的方法,但不包括父类的方法
getDeclaredMethod(String name,Class<?>..parameterTypes)获得特定名称和参数列表的方法,包括private修饰的方法

Method类的常用方法

方法功能描述
String getName()返回该方法的名称
Class[] getParameterTypes()返回该方法的各个参数的类型
Class getReturnType()返回该方法的返回值的类型
Class[] getExceptionTypes()返回该方法可能抛出的异常
Object invoke(Object obj,Object...args)用参数args执行指定对象obj中的该方法
boolean isVarArgs()查看该成员方法是否带有可变数量的参数
int getModifiers()获得可以解析出该方法所采用修饰符的整数

反射访问Person类的成员方法

package com.cxyzxc.www.reflect;import com.cxyzxc.www.entity.Person;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Demo04GetMethods {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//获取Class对象Class PersonClass1 = Person.class;Person person1 = new Person();System.out.println("-----------------------获取所有public修饰的方法(包括Object类中的方法)-----------------------");Method[] methods1 = PersonClass1.getMethods();//遍历输出所有的方法for(Method method : methods1){//输出方法名称System.out.println("方法名:"+method.getName());}System.out.println("-----------------------获取所有方法(不包括Object类中的方法)-----------------------");Method[] methods2 = PersonClass1.getDeclaredMethods();//遍历输出所有的方法for(Method method : methods2){//输出方法名称System.out.println("方法名:"+method.getName());}System.out.println("-----------------------获取指定名称的方法并使用(无参方法)-----------------------");Method m1 = PersonClass1.getMethod("eat");//调用方法m1.invoke(person1);//等价于person.eat()System.out.println("-----------------------获取指定名称的方法并使用(有参方法)-----------------------");Method m2 = PersonClass1.getMethod("eat",int.class);//调用方法m2.invoke(person1,5);//等价于person.eat(5)System.out.println("-----------------------获取指定名称的私有方法并使用(私有方法)-----------------------");Method m3 = PersonClass1.getDeclaredMethod("sleep");//因为方法是私有方法,要设置访问权限才能访问m3.setAccessible(true);//调用方法m3.invoke(person1);System.out.println("-----------------------判断方法的返回值类型-----------------------");Method m4 = PersonClass1.getMethod("getAge");System.out.println("方法返回值类型:"+m4.getReturnType());}
}

运行结果


http://www.ppmy.cn/devtools/23616.html

相关文章

整理好了!2024年最常见 100 道 Java基础面试题(十七)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常见 100 道 Java基础面试题&#xff08;十六&#xff09;-CSDN博客 三十三、Java 中常见的异常有哪些&#xff1f; Java中常见的异常很多&#xff0c;它们主要分为两大类&#xff1a;受检查异常&#xff08;Checked Exce…

php反序列化逃逸

php反序列化逃逸 逃逸是php中反序列化时的恶意利用&#xff0c;以ctf为例演示 第一段演示 逃逸为ctf反序列化的内容&#xff0c;主要是对序列化对象进行过滤&#xff0c;其中替换串长度不一致&#xff0c;造成字符逃逸。攻击者可以构造恶意的payload&#xff0c;改变对象中的…

毕业答辩的提问怎么回复?

(1&#xff09;论文采用了哪些与本专业相关的研究方法 本论文采用了[定量研究/定性研究/混合方法研究]&#xff0c;包括[调查问卷、实验、案例分析、文献综述等]&#xff0c;以确保研究的全面性和可靠性。 &#xff08;2&#xff09;论文中的核心概念是什么&#xff1f; 论文…

大数据分析与应用实验(黑龙江大学)

实验一 Hadoop伪分布式实验环境搭建与WordCount程序 一、实验目的 1、学习搭建Hadoop伪分布式实验环境 2、在伪分布式实验环境下运行WordCount程序 二、实验内容 1、搭建Hadoop伪分布式实验环境&#xff0c;并安装Eclipse。 2、在Eclipse环境下&#xff0c;编写并执行Wor…

httpClient提交报文中文乱码

httpClient提交中文乱码&#xff0c;ContentType类型application/json 指定提交参数的编码即可 StringEntity se new StringEntity(paramBody.toJSONString(),"UTF-8");se.setContentType("application/json");context.httpPost.setHeader("Cookie&…

边OTG边充电芯片LDR6500

随着科技的飞速发展&#xff0c;智能移动设备已成为我们生活中不可或缺的一部分。而在这些设备的连接与数据传输中&#xff0c;Type-C接口以其高效、便捷的特性逐渐占据了主导地位。OTG&#xff08;On-The-Go&#xff09;技术则进一步扩展了Type-C接口的功能&#xff0c;使得设…

ElasticSearch复合查寻

FunctionScore主要是在原始查询的基础上去修改一下算分的。 而BooleanQuery布尔查询&#xff0c;它不会去修改算分&#xff0c;而是把多个查询语句组合在一起形成新查询。这些被组合的查询语句&#xff0c;我们都称之为叫子查询了&#xff0c;这些子查询&#xff0c;它的组合方…

如何制作一个后台管理页面的路由以及功能实现

后台 文章目录 后台一、RESFUL API二、各模块路由处理1、分类模块1.1、GET /list 分类列表1.2、POST / 新增|编辑分类1.3、DELETE / 删除分类1.4、GET /option 分类选项列表 2、评论模块2.1、GET /list 评论列表2.2、DELETE / 删除评论2.3、PUT /review 修改评论审核 3、留言模…