整体介绍
◆介绍反射及作用
◆讲解反射四个核心类
◆反射在项目中的应用
介绍反射及作用
什么是反射Reflect
◆反射(Reflect)是在运行时动态访问类与对象的技术
◆反射是JDK1.2版本后的高级特性,隶属于java.lang.reflect
◆大多数Java框架都基于反射实现参数配置、动态注入等特性
初始反射技术
实现四则运算:
加法实现接口:
Addition.java
传统的创建对象方式:
如果增加乘法运算需要在com.imooc.reflect新建Multiplication.java文件后,还要在源代码文件中添加
进行创建对象,然后重新打包部署非常麻烦
而使用反射技术不必修改源代码,在运行时动态创建新增的对象
反射创建对象更加灵活:
mathOperation = (MathOperation) Class.forName("com.imooc.reflect." + op).newInstance();
即为使用反射技术动态创建对象,object强制类型转换为MathOperation对象不必在修改源代码
object是所有类的父类
正是因为JAVA提供了反射技术,才有mybatis和Spring等高级框架
反射四个核心类
◆Class类
◆Constructor构造方法类
◆Method方法类
◆Field成员变量类
一个类里刚好包含这几种
Class类
◆Class,是VM中代表”类和接口”的类
◆Class对象具体包含了某个特定类的结构信息
◆通过Class对象可获取对应类的构造方法/方法/成员变量
Class核心方法
Class.forName需要捕捉异常
如何使用带参构造方法实例化对象?
Method方法类
◆Method对象指代某个类中的方法的描述
◆Method对象使用classObj..getMethod()方法获取
◆通过Method对象调用指定对象的对应方法
Method类核心方法
新建methodSample.java
调用带参构造方法
使用带参构造方法实例化:
调用方法:
Method updateSalaryMethod = employeeClass.getMethod("updateSalary" , new Class[]{
Float.class
});
Employee employee1 = (Employee)updateSalaryMethod.invoke(employee,new Object[]{1000f});
当只有updateSalary方法名是不行的,因为重载函数可以方法名相同,参数不同而调用不同方法,所以还要写上参数类型new Class[]{Float.class}
得到方法后需要使用invoke()方法执行,employee表示执行对象,new Object[]{1000f}为对象数组,表示上调1000元,float类型,返回的是object对象,需要强制转换为Employee对象
Field成员变量类
◆Field对应某个具体类中的成员变量的声明
◆Field对象使用classObj.getFieldO方法获取
◆通过Field对象可为某对象成员变量赋值/取值
Field类核心方法
新建Field.java文件
选中需要捕获异常的代码块,选择菜单栏的code→suround with→trycatch即可快速捕获异常
employee表示get获取或者set要设置指定的类
如何访问private修饰的私有变量?
getDeclared系列方法说明
◆getDeclaredConstructor(s) Method(s) Field(s)获取对应对象
◆getConstructor(s) Method(s) Field(s)只能获取public对象
◆访问非作用域内构造方法、方法、成员变量,会抛出异常
新建getDeclaredSample.java文件
Field[] fields = employeeClass.getDeclaredFields();
获取成员变量数组,使用field.getModifiers()
获取是public修饰还是private修饰,public返回1,private返回2
函数方法:
使用下列代码获取上述方法:
String methodName = "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
每个函数都有get开头,然后后一个字母为大写,field.getName().substring(0,1).toUpperCase()
即转换为大写,substring(0,1)表示截取一个字符,而substring(1)表示从第二个字符开始截取后面所有
Object ret = getMethod.invoke(employee);
只需传入employee对象即可,因为执行的函数都是无参的,而且此处不能强制类型转换,因为执行的方法的类型都不一样,有String、Float、void类型,所以使用object父类即可
反射在项目中的应用案例
利用反射技术实现i8n
在com.imooc.i18n中新建I18N.Java接口文件
继续新建Zhcn.java文件
继续新建EN.java文件
我们需要进行灵活配置,不能写死在java文件中,
在src文件夹下新建config.properties文件,用来保存配置信息通过修改配置文件来切换语言
创建入口类Application.java
Application.class.getResource("/config.properties").getPath();
获取配置文件详细路径
configPath = new URLDecoder().decode(configPath,"UTF-8");
得到不包含任何特殊编码的url路径
properties.load(new FileInputStream(configPath));
加载文件
String language = properties.getProperty("language");
得到language配置选项
I18N i18n = (I18N)Class.forName(language).newInstance();
加载并实例化对象
因为实现的都是I18N接口,可以强制转换为I18N类型
对于不同地区只需添加不同地区的语言java文件即可,然后在配置文件中进行修改即可
如添加了英语版本,只需将language=com.imooc.i18n.Zhcn
修改为language=com.imooc.i18n.EN