定义
- 将类的各个组成部分封装为其他对象,这就是反射机制.反射是开发框架的灵魂.
获取Class字节码中类的三种方法
- Class.forName("全类名"),将字节码加载进内存,返回class对象---多用于配置文件
- 类名.class:通过类名的属性class获取---多用于传参
- 对象.getclass():getclass在Object对象中定义---多用于对象的字节码获取
同一个字节码(*.class)在程序运行中只会被加载一次,所以无论用什么方法获取都是同一个字节码
代码:获取成员变量,方法,构造器,类名的方法
public class Reflect
{
public static void main(String[] args) throws Exception
{
//方法1
Class cls1 = Class.forName("java_study.Book");
System.out.println(cls1);
//方法2
Class cls2 = Book.class;
System.out.println(cls2);
//方法3
Book b = new Book(50);
Class cls3 = b.getClass();
System.out.println(cls3);
System.out.println(cls1==cls2);
//获取public成员变量
Field[] fs = cls1.getFields();
for(Field f:fs)
{
System.out.println(f);
}
//获取成员变量后进行操作:get和set
Field date = cls1.getField("date");
Book b2 = new Book(56);
Object value = date.get(b2);//参数是传入一个该类的对象
System.out.println(value);
date.set(b2,"2020-40-20");
System.out.println(b2);
//不考虑修饰符,获取所有成员变量
Field[] fields2 = cls2.getDeclaredFields();
for(Field f:fields2)
{
System.out.println(f);
}
//修改私有成员变量时会报错,需要忽略安全检查,暴力反射
Field name = cls2.getDeclaredField("name");
name.setAccessible(true);//忽略安全检查
Book b3 = new Book(100);
Object v2 = name.get(b3);
name.set(b3,"格局");
System.out.println(b3);
//获取构造方法
Constructor constructor = cls3.getConstructor(String.class,int.class,int.class);//里面是传入构造参数
System.out.println(constructor);
//获取构造器的目的就是用来创建对象
//创建对象
Object book4 = constructor.newInstance("一千零一夜",4,52);
System.out.println(book4);
//获取成员方法,作用就是执行方法
Method show = cls1.getMethod("showbook");
Method setName = cls1.getMethod("setName", String.class);
setName.invoke(book4,"平凡的世界");
show.invoke(book4);//用invoke方法执行方法,第二个参数是方法的参数,第一个是对象
//获取所有Public方法,包括Object的方法
Method[] ms = cls1.getMethods();
for(Method m:ms)
{
m.setAccessible(true);//暴力映射
String M_name = m.getName();//获取方法名称
System.out.println(m);
System.out.println(M_name);
}
//获取类名
String className = cls1.getName();
System.out.println(className);
}
}
反射框架一般步骤
- 将需要创建对象的全类名和方法定义在配置文件中
- 在程序中读取配置文件
- 使用反射技术加载类文件进入内存
- 创建对象,执行方法
* 需求:写一个“框架”,可以传入任意类,并且用该类创建对象,然后执行其中任意方法
*框架类的前提就是:不能改变该框架类的任何代码,并且能创建任意类的对象,执行任意方法
*实现:配置文件,反射
*步骤:1.将需要创建对象的全类名和方法定义在配置文件中
* 2.在程序中读取配置文件
* 3.使用反射技术加载类文件进入内存
* 4.创建对象
* 5.执行方法
*/
public class ReflectExample
{
public static void main(String[] args) throws Exception
{
//1.加载配置文件:创建properties对象,它是一个集合map
Properties properties = new Properties();
ClassLoader classLoader = ReflectExample.class.getClassLoader();//字节码加载器
InputStream is = classLoader.getResourceAsStream("config.properties");//获取配置文件中的字节流
properties.load(is);
//2.获取配置文件中定义的数据
String className = properties.getProperty("className");//获取内容
String methodName = properties.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);//就是转换为.class字节码
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}