问题的提出
-
需求
- 根据配置文件re.properties指定信息,创建Cat对象并调用方法hi
- classfullpath=com.hspedu.Cat
- method=hi
-
Cat.java
package com.hspedu;
public class Cat {
public void hi(){
System.out.println("喵喵喵~");
}
}
- re.properties
classFullPath=com.hspedu.Cat
method=hi
- ReflectionQuestion.java
public class ReflectionQuestion {
public static void main(String[] args) {
//传统的方式创建Cat
Cat cat = new Cat();
cat.hi();
//使用properties配置文件创建类,不适用反射则无法创建类
}
}
初识反射
public class ReflectionQuestion {
public static void main(String[] args) throws Exception {
//传统的方式创建Cat
Cat cat = new Cat();
cat.hi();
//使用properties配置文件创建类,不适用反射则无法创建类
//---------------使用反射机制解决------------------
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/re.properties"));
//获取配置文件中的类路径和方法
String classFullPath = properties.get("classFullPath").toString();
String methodName = properties.get("method").toString();
//1.加载类
Class aClass = Class.forName(classFullPath);
//2.通过aClass得到你加载的类 com.hspedu.Cat
Object o = aClass.newInstance();
//3.通过aClass得到加载类com.hspedu.Cat的methodName(hi)方法。在反射中可以把方法当做对象
Method method = aClass.getMethod(methodName);
//通过method调用方法,即通过方法对象来实现调用方法
method.invoke(o); //输出 喵喵喵~
}
}
- 在不修改源码的情况下来控制程序(修改配置),新建cry方法。修改配置文件method=cry则直接调用cry方法不需要修改ReflectionQuestion的源码
public class Cat {
public void hi(){
System.out.println("喵喵喵~");
}
public void cry(){
System.out.println("wuwuwu~");
}
}
反射机制
- Java Reflection
- 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
- 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构,这个对象就向一面镜子,透过这个镜子看到类的结构,所以,形象的称之为反射
- Java反射机制可以完成
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
- 反射相关的主要类
- java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
- java.lang.reflect。Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
- Cat.java
public class Cat {
public String name = "小猫";
public Cat(){
}
public Cat(String name){
this.name = name;
}
public void hi(){
System.out.println("喵喵喵~");
}
public void cry(){
System.out.println("wuwuwu~");
}
}
public class Reflection01 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/re.properties"));
//获取配置文件中的类路径和方法
String classFullPath = properties.get("classFullPath").toString();
String methodName = properties.get("method").toString();
//加载类
Class aClass = Class.forName(classFullPath);
//通过aClass得到你加载的类 com.hspedu.Cat
Object o = aClass.newInstance();
//通过aClass得到加载类com.hspedu.Cat的methodName(hi)方法。在反射中可以把方法当做对象
Method method = aClass.getMethod(methodName);
//通过method调用方法,即通过方法对象来实现调用方法
method.invoke(o); //输出 喵喵喵~
//得到name字段,不能获取私有的属性
Field nameField = aClass.getField("name");
// 传统写法:对象.成员变量 反射: 成员变量.get(对象)
System.out.println(nameField.get(o)); //输出 小猫
}
}
- 反射优点和缺点
- 优点:可以动态的创建爱你和使用对象(也是框架底层核心),使用灵活
- 缺点:使用反射基本是解释执行,对执行速度有影响