一个需求引入反射
根据配置文件 re.properties
指定信息,创建 Cat
对象并调用方法 hi()
classfullpath=reflection_.Cat
method=hi
快速入门
package reflection_;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 11:06 2021/9/28
*/
public class ReflectionQuestion {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// 根据配置文件 re.properties 创建 Cat 对象并调用 hi() 方法
// 传统方式:
// 1. 使用 Properties 对象读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.getProperty("classfullpath").toString(); // 字符串
String methodName = properties.getProperty("method").toString();
System.out.println("classfullpath = " + classfullpath);
System.out.println("method = " + methodName);
// 2. 创建对象
// new classfullpath(); 编译不通过,无法通过配置文件方式 new 对象
// new reflection_.Cat(); // 可以实现
// 3. 使用反射机制解决
// (1) 加载类,返回 Class 类型的对象 aClass
Class aClass = Class.forName(classfullpath);
// (2) 通过 aClass.newInstance() 得到你加载的类 reflection_.Cat 的对象实例
Object o = aClass.newInstance();
System.out.println(o.getClass()); // o 的运行类型:class reflection_.Cat
// (3) 通过 aClass.getMethod() 得到你加载的类 reflection_.Cat 的 methodName"hi" 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method = aClass.getMethod(methodName);
// (4) 通过 method 调用方法,即通过方法对象来实现调用方法
System.out.println("===================");
method.invoke(o); // 传统方法:对象.方法() 反射:方法.invoke(对象)
}
}
反射机制
- 反射机制允许程序在运行期间借助 ReflectionAPI 取得任何类的内部信息(比如:成员变量、成员方法、构造器等),并能操作对象的属性及方法,反射在设计模式和框架底层都会用到
- 加载完类之后,在堆中就产生了一个 Class 类型的对象,代表你所加载的类,每一个类只有一个 Class 类型的对象,这个对象包含了类的完整结构信息。
Java反射机制可以完成
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
反射相关的主要类
- java.lang.Class:代表一个类,Class 对象表示某个类加载后在堆中的对象
- java.lang.reflect.Method:代表类的方法,Method 对象表示某个类的方法
- java.lang.reflect.Field:代表类的成员变量,Field 对象表示某个类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法 Constructor
package reflection_;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 14:43 2021/9/28
*/
public class Reflection01 {
public static void main(String[] args) throws Exception {
// 根据配置文件 re.properties 创建 Cat 对象并调用 hi() 方法
// 传统方式:
// 1. 使用 Properties 对象读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.getProperty("classfullpath").toString(); // 字符串
String methodName = properties.getProperty("method").toString();
// 3. 使用反射机制解决
// (1) 加载类,返回 Class 类型的对象 aClass
Class aClass = Class.forName(classfullpath);
// (2) 通过 aClass.newInstance() 得到你加载的类 reflection_.Cat 的对象实例
Object o = aClass.newInstance();
System.out.println(o.getClass()); // o 的运行类型:class reflection_.Cat
// (3) 通过 aClass.getMethod() 得到你加载的类 reflection_.Cat 的 methodName"hi" 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method = aClass.getMethod(methodName);
// (4) 通过 method 调用方法,即通过方法对象来实现调用方法
System.out.println("===================");
method.invoke(o); // 传统方法:对象.方法() 反射:方法.invoke(对象)
// java.lang.reflect.Field:代表类的成员变量,Field 对象表示某个类的成员变量
// 得到 name 字段,getField 不能获取私有属性
Field nameField = aClass.getField("age");
System.out.println(nameField.get(o)); // 传统方法:对象.成员变量 反射:成员变量.get(对象)
// java.lang.reflect.Constructor:代表类的构造方法 Constructor
// () 中可以指定构造器参数类型,返回无参构造器
Constructor constructor = aClass.getConstructor();
System.out.println(constructor);
// () 中传入 String.class,就是 String 类的 Class 对象
Constructor constructor1 = aClass.getConstructor(String.class);
System.out.println(constructor1); // Cat(String name)
}
}