版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
单元9Java反射机制Java程序设计基础教程(AI助学)(慕课版)人民邮电出版社一位汽车爱好者对汽车发动机的构造和性能非常感兴趣,希望能够动态地了解不同品牌汽车的发动机参数,并根据需求调整发动机的参数,以获得更好的性能表现。学习反射机制如同探索汽车发动机的内部工作原理。首先,需要了解反射的基本概念,就像汽车爱好者需要了解汽车发动机的工作原理一样。其次,深入研究Class类的使用,类似于深入研究不同汽车品牌的发动机技术,包括获取类的信息和操作类的属性、方法。最后,探讨反射在实际应用中的场景,以及如何利用反射处理注解、开发通用组件等。这就像在汽车维修过程中,根据车辆的具体情况调整发动机参数以提升性能。反射机制可以在程序运行时动态获取和操作类信息,增强Java开发的灵活性和智能性。通过本单元的学习,读者可以掌握在程序运行时动态获取和操作类信息的技能,能够灵活应用反射机制,增强Java开发的灵活性和智能性,就像调整汽车发动机参数一样,让Java应用程序的性能更加出色。本章导读Thechapter’sintroduction目录导航9.1反射概述9.2
Class类概述9.3
Class类的使用9.5
【商业实例】“银行提款机”项目——反射写入操作时间9.6
【综合实训】对象的复制9.4反射的应用9.1反射概述反射(Reflection)是Java的一个强大特性,允许程序在运行时动态地获取类的信息、调用方法、操作属性,甚至实例化对象,而无须在编译时确定类的具体实现。反射的核心是Class类,它是Java反射机制的基础,可以用来表示和操作类的信息。反射机制可以在程序运行时动态加载类,这为实现插件化架构和灵活配置提供了途径动态加载类0405反射使得编写通用代码和框架变得更加容易,可以根据需要在程序运行时处理不同的类和对象实现通用代码和框架06反射机制常用于实现自定义注解的解析和处理,为程序添加元数据信息注解处理01反射允许程序在运行时获取类的名称、方法、属性、构造方法等信息,实现类的动态解析动态获取类信息02通过反射可以在程序运行时实例化对象,而不需要提前知道类的具体类型,这为灵活的对象创建提供了可能实例化对象03反射可以调用类的方法和操作类的属性,包括私有方法和私有属性,使得程序能够在运行时动态地调用和修改类的行为调用方法和操作属性目录导航9.1反射概述9.2
Class类概述9.3
Class类的使用9.5
【商业实例】“银行提款机”项目——反射写入操作时间9.6
【综合实训】对象的复制9.4反射的应用9.2Class类概述Class类是Java反射机制的核心类,它代表Java类的类型,也就是类的元数据。每个被加载的类都有一个对应的Class对象。类的名称:通过getName()方法获取,返回类的全限定名,包括包名,如java.lang.String类的修饰符:通过getModifiers()方法获取,返回一个整数,表示类的修饰符,如public、abstract等类的包:通过getPackage()方法获取,返回Package对象,表示类所在的包父类:通过getSuperclass()方法获取,返回表示父类的Class对象。如果当前类是接口或者Object类,则返回null实现的接口:通过getInterfaces()方法获取,返回一个Class对象数组,表示该类实现的接口类的构造器:通过getConstructors()方法获取,返回一个Constructor对象数组,表示类的所有公共构造方法类的方法:通过getMethods()方法获取,返回一个Method对象数组,表示类的所有公共方法类的属性:通过getFields()方法获取,返回一个Field对象数组,表示类的所有公共属性9.2Class类概述要获取Class对象,可以使用以下3种方法之一。使用.class语法这是获取Class对象最简单的方法,只需要在类名后面加上.class即可使用Object类的getClass()方法如果已经有了一个对象实例,则可以使用这个实例的getClass()方法获取它的Class对象使用Class类的forName()方法这是一个静态方法,可以通过类的全名(包括包名)获取Class对象目录导航9.1反射概述9.2
Class类概述9.3
Class类的使用9.5
【商业实例】“银行提款机”项目——反射写入操作时间9.6
【综合实训】对象的复制9.4反射的应用9.3.1使用无参构造器实例化对象通过反射使用无参构造器实例化对象是一种常见的做法。当一个类中没有定义任何构造方法时,Java编译器会自动提供一个默认的无参构造方法。可以使用这个默认的无参构造方法来创建对象。示例如下packageorg.example.reflex;importjava.lang.reflect.Constructor;publicclassMyClass{privateStringmessage;publicMyClass(){this.message="无参构造器实例化";}publicvoidprintMessage(){System.out.println(this.message);}publicstaticvoidmain(String[]args){try{//获取MyClass类的Class对象
Class<?>clazz=Class.forName("org.example.reflex.MyClass");//获取MyClass类的无参构造器对象
Constructor<?>constructor=clazz.getConstructor();//通过无参构造器创建MyClass类的实例
Objectinstance=constructor.newInstance();//调用printMessage()方法
clazz.getMethod("printMessage").invoke(instance);}catch(Exceptione){e.printStackTrace();}}}在这个示例中:首先,通过Class.forName()方法获取MyClass类的Class对象。其次,使用getConstructor()方法获取MyClass类的无参构造器对象。再次,使用Constructor对象的newInstance()方法创建MyClass类的实例。最后,使用getMethod()方法获取printMessage()方法,并通过invoke()方法调用它。运行以上代码,运行结果如图9.1所示。图9.1通过反射使用无参构造器实例化对象示例结果9.3.2使用有参构造器实例化对象通过反射使用有参构造器实例化对象是为类提供初始数据的常见方式。有参构造器是一个带有参数的构造方法,用于在创建对象时传递初始值。示例如下:packageorg.example.reflex;importjava.lang.reflect.Constructor;publicclassMyClass{privateStringmessage;publicMyClass(Stringmessage){this.message=message;}publicvoidprintMessage(){System.out.println(this.message);}publicstaticvoidmain(String[]args){try{//获取MyClass类的Class对象
Class<?>clazz=Class.forName("org.example.reflex.MyClass");//获取MyClass类的带有一个String参数的构造器对象
Constructor<?>constructor=clazz.getConstructor(String.class);//通过有参构造器创建MyClass类的实例
Objectinstance=constructor.newInstance("有参构造器入参");//调用printMessage()方法
clazz.getMethod("printMessage").invoke(instance);}catch(Exceptione){e.printStackTrace();}}}在这个示例中,MyClass类定义了一个有参构造器,以接收参数message。在main()函数中,向有参构造器传递参数,创建一个MyClass实例,这样就实现了对象的实例化。有参构造器允许在创建对象时为对象的属性提供特定的初始值。运行以上代码,运行结果如图9.2所示。图9.2通过反射使用有参构造器实例化对象示例结果目录导航9.1反射概述9.2
Class类概述9.3
Class类的使用9.5
【商业实例】“银行提款机”项目——反射写入操作时间9.6
【综合实训】对象的复制9.4反射的应用9.4.1获取类实现的所有接口反射机制可以用来获取一个类实现的所有接口。通过Class类的getInterfaces()方法,可以获取一个类实现的所有接口的Class对象数组。示例如下:importjava.util.Arrays;publicclassMain{publicstaticvoidmain(String[]args){//获取String类的Class对象
Class<?>stringClass=String.class;//获取String类实现的所有接口
Class<?>[]interfaces=stringClass.getInterfaces();//输出所有接口的名称
System.out.println("String类实现的接口有:");for(Class<?>iface:interfaces){System.out.println(iface.getName());}}}在这个示例中:首先,获取了String类的Class对象。其次,使用getInterfaces()方法获取了该类实现的所有接口的Class对象数组。最后,通过循环遍历这个数组,输出所有接口的名称。运行以上代码,运行结果如图9.3所示。图9.3通过反射获取类实现的所有接口示例结果9.4.2获取类的所有方法在Java中,可以使用反射机制来获取一个类中所有的方法。具体地说,可以通过类的Class对象的getDeclaredMethods()方法获取该类的所有方法,包括静态方法和非静态方法。这个方法返回一个Method对象数组。importjava.lang.reflect.Method;classMyClass{publicvoidmyMethod(){System.out.println("commentmethod");}publicstaticvoidmyStaticMethod(){System.out.println("staticmethod");}}publicclassTestMain{publicstaticvoidmain(String[]args){//获取MyClass类的Class对象
Class<?>myClassClass=MyClass.class;//获取MyClass类的所有方法
Method[]methods=myClassClass.getDeclaredMethods();//输出MyClass类的所有方法的名称
System.out.println("MyClass所有方法有:");for(Methodmethod:methods){System.out.println(method.getName());}}}在这个示例中,MyClass类中有一个静态方法和一个非静态方法,通过该类Class对象的getDeclaredMethods()方法可以获取类的所有方法,并依次输出方法名称,如图9.4所示。图9.4通过反射获取类的所有方法示例结果9.4.3获取类的所有属性在Java中,可以使用反射机制来获取类的属性。通过类的Class对象,可以获取类中定义的所有属性,包括公共、私有、受保护的等各种类型的属性。importjava.lang.reflect.Field;classMyClass{privateintprivateField;publicStringpublicField;protecteddoubleprotectedField;intdefaultField;}publicclassMain{publicstaticvoidmain(String[]args){//获取MyClass类的Class对象
Class<?>myClassClass=MyClass.class;//获取MyClass类的所有属性
Field[]fields=myClassClass.getDeclaredFields();//输出MyClass类的所有属性名
System.out.println("MyClass类的所有属性名:");for(Fieldfield:fields){System.out.println(field.getName());}}}在这个示例中,MyClass类中定义了4个属性,分别是privateField(私有属性)、publicField(公共属性)、protectedField(受保护的属性)和defaultField(默认属性)。在Main类的main()函数中,获取了MyClass类的Class对象,并使用getDeclaredFields()方法获取该类的所有属性,通过循环遍历这个属性数组,输出每个属性的名称。运行以上代码,运行结果如图9.5所示。图9.5通过反射获取类的所有属性示例结果目录导航9.1反射概述9.2
Class类概述9.3
Class类的使用9.5
【商业实例】“银行提款机”项目——反射写入操作时间9.6
【综合实训】对象的复制9.4反射的应用【商业实例】“银行提款机”项目——反射写入操作时间在本实例中,需要进行几个关键修改。首先,修改创建账户的程序以接收包含账户、余额和创建时间的AccountInfo对象作为参数,并通过main()函数调用来创建账户。其次,创建一个方法,该方法接收一个Object对象作为参数,但实际上用于向AccountInfo对象的createdAt属性中写入当前时间作为操作时间。最后,无论main()函数在创建账户时是否直接传入createdAt属性,都要确保在创建账户时该属性会被赋予当前时间值,从而保证账户创建时间的完整性和准确性。【商业实例】“银行提款机”项目——反射写入操作时间任务1:修改创建账户的程序importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.Timestamp;importjava.util.Date;publicclassCreateAccount{//数据库连接URLprivatestaticfinalStringDB_URL="jdbc:MySQL://localhost:3306/test";//数据库用户名
privatestaticfinalStringUSER="root";//数据库密码
privatestaticfinalStringPASS="password";publicstaticvoidmain(String[]args){//创建账户lisiAccountInfolisiAccount=newAccountInfo();lisiAccount.setAccount("lisi");修改创建账户的程序,传入一个AccountInfo对象,对象中包含account、balance、createdAt3个属性,使用main()函数调用创建账户的方法,成功创建账户。【商业实例】“银行提款机”项目——反射写入操作时间lisiAccount.setBalance(100D);lisiAccount.setCreatedAt(newTimestamp(newDate().getTime()));createAccount(lisiAccount);//创建账户wangwuAccountInfowangwuAccount=newAccountInfo();wangwuAccount.setAccount("wangwu");wangwuAccount.setBalance(100D);wangwuAccount.setCreatedAt(newTimestamp(newDate().getTime()));createAccount(wangwuAccount);}publicstaticvoidcreateAccount(AccountInfoaccountInfo){try{//1.注册JDBC驱动
Class.forName("com.MySQL.cj.jdbc.Driver");//2.建立数据库连接
Connectionconn=DriverManager.getConnection(DB_URL,USER,PASS);//3.执行插入操作
Stringsql="INSERTINTOAccounts(account,balance,created_at)VALUES(?,?,?)";PreparedStatementpstmt=conn.prepareStatement(sql);pstmt.setString(1,accountInfo.getAccount());【商业实例】“银行提款机”项目——反射写入操作时间pstmt.setDouble(2,accountInfo.getBalance());pstmt.setTimestamp(3,accountInfo.getCreatedAt());pstmt.executeUpdate();System.out.println("成功创建账户:"+accountInfo.getAccount());//4.清理环境
pstmt.close();conn.close();}catch(Exceptione){e.printStackTrace();}}//内部类AccountInfo,用于封装账户信息
staticclassAccountInfo{privateStringaccount;privatedoublebalance;privateTimestampcreatedAt;publicStringgetAccount(){returnaccount;}publicvoidsetAccount(Stringaccount){this.account=account;
}publicdoublegetBalance(){returnbalance;}publicvoidsetBalance(doublebalance){this.balance=balance;}publicTimestampgetCreatedAt(){returncreatedAt;}publicvoidsetCreatedAt(TimestampcreatedAt){this.createdAt=createdAt;}}}【商业实例】“银行提款机”项目——反射写入操作时间任务2:为createdAt属性补充当前时间publicstaticvoidsetCreatedAt(Objectobj){try{//获取对象的类信息
Class<?>aClass=obj.getClass();//获取类中的createdAt属性
FieldcreatedAt=aClass.getDeclaredField("createdAt");//设置createdAt属性可访问,即使它是私有的
createdAt.setAccessible(true);//获取当前时间
TimestampcurrentTime=newTimestamp(newDate().getTime());//将对象的createdAt属性值设置为当前时间
createdAt.set(obj,currentTime);}catch(Exceptione){//输出异常信息,以便进行调试和日志记录
e.printStackTrace();}}创建一个方法,其输入参数为Object对象,功能是为createdAt属性补充当前时间。【商业实例】“银行提款机”项目——反射写入操作时间任务3:createdAt属性值设置/***main()函数,程序入口*演示创建账户的流程,包括初始化账户信息、自动设置创建时间和将账户信息保存到数据库中*本例中创建了lisi和wangwu两个账户,每个账户的初始余额均为100元*/publicstaticvoidmain(String[]args){//创建账户lisiAccountInfolisiAccount=newAccountInfo();lisiAccount.setAccount("lisi");lisiAccount.setBalance(100D);setCreatAt(lisiAccount);createAccount(lisiAccount);//创建账户wangwuAccountInfowangwuAccount=newAccountInfo();wangwuAccount.setAccount("wangwu");wangwuAccount.setBalance(100D);setCreatedAt(wangwuAccount);createAccount(wangwuAccount);无论main()函数调用创建账户的方法时是否输入createdAt参数,此属性都有值。【商业实例】“银行提款机”项目——反射写入操作时间}/**
*设置对象的createdAt属性值为当前时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 水文勘测船工岗前进度管理考核试卷含答案
- 2026年版三高症知识指南解读
- 燃气公司技术人员培训考试试题及答案
- 2026年企业人力资源管理师之一级人力资源管理师真题练习试卷附答案
- 微机原理期末考试试卷(有答案)
- 铁路货运组织期末考试试题及答案(A卷)
- 朔州市2026年上半年全国英语等级考试(PETS)复习试题及答案高分策略(全新版)第五级
- 食品安全员能力测试试题B卷附答案
- 2026年社区食品安全协管员真题(附答案)
- 2026年平面设计师技能题库(附答案)
- 《数字经济概论》(教案大纲)
- (正式版)DB15∕T 3413-2024 《住宅小区和商业用房供配电设施规范》
- 肌骨常见疾病的超声诊断
- 2024年江苏科技大学辅导员考试真题
- DG∕TJ 08-2019-2019 膜结构检测标准
- 建筑工程土建主体部分施工方案
- 租赁仪器合同协议
- 成人原发性腹壁疝腹腔镜手术中国专家共识(2025版)解读课件
- 2024-2025学年河南省“金太阳联考”高一年级上学期期中考试数学试题(含答案)
- 2024年新北师大版八年级上册物理全册教学课件(新版教材)
- 2023年基因检测项目评估报告
评论
0/150
提交评论