当前位置: 首页 > news >正文

Java中的反射机制

1 为什么要反射?

正射:我们new创建类的实例时实际上时JVM在运行时根据这个类的class对象构造的。

反射:反射是在运行时通过类的class对象获得的内部定义信息

提出反射应用场景: 当前我们需要实例一个对象,但是不确定创建对象,那么就需要动态创建了。 (通过传入参数进行确定要使用哪一种实体)

反射可以在程序运行过程中动态获取类信息和调用类方法。通过反射构造类实例,代码最终会演变成下面这样。

public <T> T getPoJo(String className) throws Exception {Class clazz = Class.forName(className);return (T) clazz.newInstance();
}

反射的思想

        在程序运行过程中确定和解析数据类的类型。

反射的作用

        对于在编译其无法确定使用哪个数据类的场景,通过反射可以在程序运行时构造不同的数据类实例

2  什么是Java反射?

3  Java反射机制的实现

class类

正在运行在内存中的所有类都是该类的实例对象,每个Class类都包含本类的所有信息

反射机制的实现

public class Demo01 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {Person person = new Person();//1.获取类的字节码文件对象//方法一:直接通过一个class的静态变量class获取:Class cls1=Person.class;System.out.println(cls1);//方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()方法获取:Class cls2=person.getClass();System.out.println(cls2);//方法三:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取:Class cls3=Class.forName("apesource.knowledge01.refStudy.Person");System.out.println(cls3);System.out.println("cls1 == cls2?:"+(cls1 == cls2));System.out.println("cls2 == cls3?:"+(cls2 == cls3));System.out.println("cls1 == cls3?:"+(cls1 == cls3));//通过Class.newInstance()可以创建类实例,要求实例时必须要有公共的无参构造方法,否则报错Object object=cls1.newInstance();System.out.println(object);}
}

类内部主要信息

  • Field:所有属性
  • Method:所有方法
  • Constructor:所有构造方法

class类常用的方法

类型

访问方法

返回值类型

说明

包路径

getPackage()

Package 对象

获取该类的存放路径

类名称

getName()

String 对象

获取该类的名称

继承类

getSuperclass()

Class 对象

获取该类继承的类

实现接口

getlnterfaces()

Class 型数组

获取该类实现的所有接口

构造方法

getConstructors()

Constructor 型数组

获取所有权限为 public 的构造方法

getDeclaredContruectors()

Constructor 对象

获取当前对象的所有构造方法

方法

getMethods()

Methods 型数组

获取所有权限为 public 的方法

getDeclaredMethods()

Methods 对象

获取当前对象的所有方法

成员变量

getFields()

Field 型数组

获取所有权限为 public 的成员变量

getDeclareFileds()

Field 对象

获取当前对象的所有成员变量

constructor类

描述 Class类中的构造方法的一个类,该类提供了关于所有描述构造方法的信息

类内部主要信息

①构造方法的访问修饰符(public / private / protected -)

②构造方法的参数

        参数的数据类型(int / double….)

        参数名字

        标注在参数上的注解

反射机制的实现

public class Demo04 {public static void main() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//1.获取类的字节码文件Class cls=Person.class;//2.获取构造方法//getConstructors()  所有被public修饰的构造方法
//        Constructor[] constructors=cls.getConstructors();//getDeclaredConstructors()  所有声明的方法Constructor[] constructors=cls.getDeclaredConstructors();for(Constructor c:constructors){System.out.println(c);}//getConstructor()  获取某个被public修饰的构造方法Constructor constructor=cls.getConstructor(String.class);System.out.println(constructor);//getDeclaredConstructor()  获取指定的某个构造方法Constructor<Person> constructor1=cls.getDeclaredConstructor(String.class,int.class);System.out.println(constructor1);//3.解剖构造方法对象//包-0  public-1  private-2 protected-4int modifier=constructor1.getModifiers();System.out.println(modifier);System.out.println("权限修饰符是否是公共的?"+ Modifier.isPublic(modifier));//获取方法的形参Parameter[] parameters=constructor1.getParameters();for(Parameter p:parameters){System.out.println(p.getType()+" "+p.getName());}System.out.println("构造方法的名字:"+constructor1.getName());//4.实例化对象constructor1.setAccessible(true);  //临时取消权限校验符Person person=constructor1.newInstance("张三",18);System.out.println(person);}
}

作用

创建目标对象

Field类

通过反射获取到一个 Field对象时,其内部包含了某个类中其中一个属性的所有信息

类内部主要信息

        ①标注在属性上的注解

        ②属性名

        ③ 属性的数据类型(boolean / double / int /String …)

        ④ 属性访问修饰符(public / private / protected)

反射机制的实现

public class Demo05 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {//1.获取类的字节码文件对象Class cls=Dog.class;//2.获取成员变量//getFields()  获取所有的public成员变量(包含父类的成员变量)Field[] fields=cls.getFields();for(Field f:fields){System.out.println(f);}System.out.println("=======================================================================");//getDeclaredFields()  获取到本类中所有声明的成员变量Field[] fields1=cls.getDeclaredFields();for(Field f:fields1){System.out.println(f);}System.out.println("========================================================================");//getField()   获取本类或父类中某个被public修饰的成员变量Field field=cls.getField("name");System.out.println(field);System.out.println("========================================================================");//getDeclaredField()  获取到本类中某个成员变量Field field1=cls.getDeclaredField("color");System.out.println(field1);System.out.println("========================================================================");//3.解剖//获取权限修饰符int modifier=field1.getModifiers();System.out.println("权限修饰符为:"+modifier);System.out.println("是否是静态成员变量?"+ Modifier.isStatic(modifier));System.out.println("是否是私有成员变量?"+Modifier.isPrivate(modifier));System.out.println("========================================================================");//获取数据类型Class typeClass=field1.getType();System.out.println("数据类型为:"+typeClass);System.out.println("========================================================================");//获取变量名String name=field1.getName();System.out.println("变量名为:"+name);//4.应用Dog dog=new Dog("旺财",3,"拉布拉多",20.0,12,"金黄");Dog dog1=new Dog();field1.setAccessible(true);  //临时取消权限校验符//获取对象dog中此成员变量的值
//        Object object=field1.get(dog);//获取静态成员变量,不依赖于对象而创建,所以获取此成员变量的值时,可以不传对象Object object=field1.get(null);System.out.println("获取到成员变量对应的值:"+object);//修改成员变量的值
//        field1.set(dog,"黑白");//设置静态成员变量值,静态成员变量共享一片空间,所以可以修改field1.set(null,"黑白");System.out.println(dog);System.out.println(dog1);}
}

Method类

描述 Class类中所有方法(不包括构造方法)的类,包括抽象方法。

类内部主要信息

① Constructor类内部主要信息相同

② 方法返回值类型(int /double…)

反射机制的实现

public class Demo07 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//1.获取Student类的字节码文件对象Class cls=Student.class;//2.获取方法//getMethods()  获取本类和父类中所有被public修饰的方法Method[] methods=cls.getMethods();for(Method m:methods){System.out.println(m);}System.out.println("===============================================================");//getDeclaredMethods()  获取本类中所有声明的方法Method[] methods1=cls.getDeclaredMethods();for(Method m:methods1){System.out.println(m);}System.out.println("===============================================================");//getMethod()   通过方法名和参数项明确要获取的本类或父类中被public修饰的方法Method method=cls.getMethod("eat",String.class);System.out.println(method);System.out.println("===============================================================");//getDeclaredMethod()   通过方法名和参数项明确要获取的本类中被声明的方法Method method1=cls.getDeclaredMethod("eat");System.out.println(method1);System.out.println("===============================================================");//3.解剖//获取权限修饰符  getModifiers()int modifier=method1.getModifiers();System.out.println("权限修饰符为:"+modifier);//获取返回值类型  getReturnType()Class returnType=method1.getReturnType();System.out.println("返回值类型为:"+returnType);//获取方法名  getName()String methodName=method1.getName();System.out.println("方法名:"+methodName);//获取参数项  getParameters()System.out.println("获取参数项");Parameter[] parameters=method.getParameters();for(Parameter p:parameters){System.out.print(p.getType()+": "+p.getName()+" ");}System.out.println();//获取异常信息  getExceptionTypes()System.out.println("获取异常信息");Class[] exceptions=method.getExceptionTypes();for(Class c:exceptions){System.out.print(c);}System.out.println("===============================================================");//4.方法的对象  invoke(obj--对象名,args..  参数值)Person student=new Student();method.setAccessible(true);Object object=method.invoke(student,"大盘鸡拌面");System.out.println(object);System.out.println("===============================================================");//5.静态方法调用(不依赖于对象)Method method2=cls.getDeclaredMethod("getUUid");method2.setAccessible(true);Object uid=method2.invoke(null);  //静态方法,可以不传入对象System.out.println(uid);System.out.println("===============================================================");//6.多态Person person=new Person();Class cls1=person.getClass();Method method3=cls1.getMethod("hello");method3.setAccessible(true);method3.invoke(person);Method method4=cls.getMethod("hello");method4.setAccessible(true);method4.invoke(student);}
}

作用

执行方法逻辑

4  反射的应用场景

  • Spring 实例化对象

当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。

  • 反射 + 工厂模式

通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。

  • JDBC连接数据库

使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动。

5  反射的优点和缺点

优点:增加程序的灵活性:面对需求变更时,可以灵活地实例化不同对象。

缺点

  • 破坏类的封装性:可以强制访问 private 修饰的信息;
  • 性能损耗:反射相比直接实例化对象、调用方法、访问变量,中间需要非常多的检查步骤和解析步骤,JVM无法对它们优化。
http://www.dtcms.com/a/320083.html

相关文章:

  • 【AxureMost落葵网】企业ERP项目原型-免费
  • 上位机知识篇篇---驱动
  • Xvfb虚拟屏幕(Linux)中文入门篇1:(wikipedia摘要,适当改写)
  • 函数、方法和计算属性
  • 计网学习笔记第3章 数据链路层(灰灰题库)
  • [激光原理与应用-169]:测量仪器 - 能量型 - 光功率计(功率稳定性监测)
  • 记录:rk3568适配开源GPU驱动(panfrost)
  • Linux中Docker Swarm实践
  • 12-netty基础-手写rpc-编解码-04
  • ubuntu 2024 安装拼音输入法
  • 【macOS操作系统部署开源DeepSeek大模型,搭建Agent平台,构建私有化RAG知识库完整流程】
  • Linux综合练习2
  • 电气设备与互感器全解析
  • 智能制造网络质量保障:德承 DX-1200多网口工控机在windows系统下的网络性能测试指南
  • 操作系统与并发底层原理多道技术
  • docker容器导出为镜像
  • 深度学习入门Day7:Transformer架构原理与实战全解析
  • 亚马逊广告运营:有什么好用的辅助工具
  • Redis配置、测试及分布式缓存实现
  • Android 之 Jetpack - Paging
  • 《C语言》函数练习题--2
  • ElasticSearch相关术语介绍
  • 使用 decimal 包解决 go float 浮点数运算失真
  • 小鸡模拟器安卓版:经典街机游戏的移动体验
  • 利用Axure与JavaScript打造动态图片上传原型:设计案例分享
  • spring-cglib代理-初探01
  • 深度学习-卷积神经网络CNN-1×1卷积层
  • Flink-1.19.0源码详解9-ExecutionGraph生成-后篇
  • UE5多人MOBA+GAS 39、制作角色上半身UI
  • 字符串匹配(重点解析KMP算法)