当前位置: 首页 > 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.lryc.cn/news/613314.html

相关文章:

  • 土壤盐分传感器与土壤电导率传感器直接的关系
  • 深入理解String类:揭秘Java字符串常量池的优化机制
  • 【2025最新版】火狐浏览器(官方版)安装-附教程
  • 飞算JavaAI深度解析:Java开发者的智能革命
  • AUTOSAR进阶图解==>AUTOSAR_EXP_BSWDistributionGuide
  • 损耗对信号质量的影响
  • Java 八大经典排序算法全解析
  • 数组指针-函数指针-回调函数
  • 人工智能——自动微分
  • Docker容器部署harbor-小白级教学
  • Dlib库是什么?白话,详细介绍版
  • python中用xlrd、xlwt读取和写入Excel中的日期值
  • GIT操作卡顿
  • 机器学习核心算法与实践要素(全篇)
  • java excel转图片常用的几种方法
  • 玳瑁的嵌入式日记D14-0807(C语言)
  • NVIDIA/k8s-device-plugin仓库中GPU无法识别问题的issues分析报告
  • Linux学习记录 DNS
  • LocalSqueeze(图片压缩工具) v1.0.4 压缩
  • nlp-句法分析
  • ClickHouse数据迁移
  • Redis持久化存储
  • 【网络运维】Linux:NFS服务器原理及配置
  • ansible-playbook之获取服务器IP存储到本地文件
  • Linux---第三天---权限
  • Idea打包可执行jar,MANIFEST.MF文件没有Main-Class属性:找不到或无法加载主类
  • 3a服务器的基本功能1之身份认证
  • LINUX-文件查看技巧,重定向以及内容追加,man及echo的使用
  • Java开发时出现的问题---架构与工程实践缺陷
  • vue开发的计算机课程页面