反射:框架设计的灵魂
*框架: 半成品软件,可以在框架的基础上进行软件开发,美化编码
*反射: 将类的各个组成部分封装为其他对象,这就是反射机制
好处:
1. 可以在程序运行过程中操作这些对象。
2. 可以解耦,提高程序的可扩展性。
Java代码在计算机中经历的三个阶段 Source阶段 Class类对象阶段 Runtime阶段
*获取Class对象的三种方式
Source阶段 1.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
*多用于配置文件,将类名定义在配置文件中。读取文件,加载类
Class类对象阶段 2.类名.class: 通过类名的属性class获取
*多用于参数传递
Runtime阶段 3.对象.getClass():getClass()方法在Object类中定义着
*多用于对象的获取字节码的方式
结论:
* 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,
不论通过哪一种方式获取的Class对象都是同一个
Class对象的功能
*1.获取成员变量们
* Field[] getFields() 获取所有public 修饰的成员变量
* Field getField(String name) 获取指定名称的public 修饰的成员变量
* Field[] getDeclaredFields() 获取所有的成员变量 不考虑修饰符
* Field getDeclareField(String name) 获取指定的成员变量 不考虑修饰符
package reflect;
import java.lang.reflect.Field;
public class ReflectDemo1 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//1.获取Person的Class对象
Class personClass=Person.class;
/*
*1.获取成员变量们
* Field[] getFields() 获取所有public 修饰的成员变量
* Field getField(String name) 获取指定名称的public 修饰的成员变量
* Field[] getDeclaredFields() 获取所有的成员变量 不考虑修饰符
* Field getDeclareField(String name) 获取指定的成员变量 不考虑修饰符
* */
//1.Field [] getFields()
Field[]fields=personClass.getFields();
for (Field field:fields){
System.out.println(field);
}
System.out.println("----------------------");
//获取指定名称的public 修饰的成员变量
Field a=personClass.getField("a");
//获取成员变量a的值
Person p=new Person();
Object value=a.get(p);
System.out.println(value);
//设置a的值
a.set(p,"张三");
System.out.println(p);
//Field [] getDeclaredFields[] 获取所有的成员变量,不考虑修饰符
Field[] declaredFields=personClass.getDeclaredFields();
for (Field declaredfield : declaredFields) {
System.out.println(declaredfield);
}
//Field getDeclaredField(String name)访问指定想成员变量,不考虑修饰符
Field d=personClass.getDeclaredField("d");
//忽略访问权限的修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2=d.get(p);
System.out.println(value2);
}
}
*2.获取构造方法们
* Constructor<?>[] getConStructors() 获取所有public 修饰的构造方法
* Constructor<T> getDeclaredConstructor(类<?>...parameterTtpes) 获取指定public 修饰的构造方法
* Constructor<T> getDeclaredConstructor(类<?>...parameterTypes) 获取所有构造方法,不考虑修饰符
* Constructor<?> [] getDeclaredConstructors() 获取指定构造方法,不考虑修饰符
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//1.获取Person的Class对象
Class personClass = Person.class;
/*2.获取构造方法们
* Constructor<?>[] getConStructors() 获取所有public 修饰的构造方法
* Constructor<T> getDeclaredConstructor(类<?>...parameterTypes) 获取指定public 修饰的构造方法
* Constructor<T> getDeclaredConstructor(类<?>...parameterTypes) 获取所有构造方法,不考虑修饰符
* Constructor<?> [] getDeclaredConstructors() 获取指定构造方法,不考虑修饰符
*/
//Constructor<T> getDeclaredConstructor(类<?>...parameterTypes) 可以传多个值
//获取指定public修饰的构造器
Constructor constructor=personClass.getConstructor(String.class,int.class);
System.out.println(constructor);
//创建带参对象
Object person=constructor.newInstance("倪涛涛",23);
System.out.println(person);
Constructor constructor1=personClass.getConstructor();
System.out.println(constructor1);
//创建无参对象
Object person2=constructor1.newInstance();
System.out.println(person2);
//空参创建无参对象的简化方法
Object o=personClass.newInstance();
System.out.println(o);
//暴力反射
//constructor.setAccessible(true);
}
}
*3获取成员方法们
* Method[] getMethod() 获取所有public 修饰的成员方法
* Method<T> getMethod(String name,类<?>...parameterTypes) 获取指定public修饰的成员方法
* Method[] getDeclaredMethods() 获取所有成员方法
* Method getDeclaredMethod(String name,类<?>...parameterTypes) 获取指定成员方法
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
/*
* *3获取成员方法们
* Method[] getMethod() 获取所有public 修饰的成员方法
* Method<T> getMethod(String name,类<?>...parameterTypes) 获取指定public修饰的成员方法
* Method[] getDeclaredMethods() 获取所有成员方法
* Method getDeclaredMethod(String name,类<?>...parameterTypes) 获取指定成员方法
*
* */
//1.获取Person的Class对象
Class personClass = Person.class;
//获取指定名称的方法
personClass.getClass();
Method eat_method=personClass.getMethod("eat");
Person p=new Person();
//执行方法 invoke(Object obj)
eat_method.invoke(p);
Method eat_method2=personClass.getMethod("eat",String.class);
//执行方法
eat_method2.invoke(p,"饭");
System.out.println("*****************");
//获取所有public修饰的方法 !!! 这里也会有父类Object类的方法
Method[]methods=personClass.getMethods();
for(Method method:methods){
System.out.println(method);
//暴力反射
method.setAccessible(true);
//获取方法名
String name=method.getName();
System.out.println("方法名"+name);
}
//获取类名
String className=personClass.getName();
System.out.println("类名"+className);//全类名: 包名+类名
}
}
*4获取类名
* String getName()
``package reflect2;
import domen.Person;
import reflect.Student;
public class reflectDemo1 {
/*
*
* *获取Class对象的三种方式
Source阶段 1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
Class类对象阶段 2.类名.class: 通过类名的属性class获取
Runtime阶段 3.对象.getClass():getClass()方法在Object类中定义着
* */
public static void main(String[] args) throws Exception {
//1. Class.forName("全类名") 即包名.类名
Class cls1=Class.forName("domen.Person");
System.out.println(cls1);
//2. 类名.class
Class cls2= Person.class;
System.out.println(cls2);
//3. 对象.getClass()
Person p=new Person();
Class cls3=p.getClass();
System.out.println(cls3);
//用==去比较三个对象
System.out.println(cls1==cls2);//true
System.out.println(cls2==cls3);//true
System.out.println(cls1==cls3);//true
Class cls4=Student.class;
System.out.println(cls1==cls4);//false
}
}
package reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//可以创建任意类的对象,可以执行任意方法
/*
* 前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
* */
// Person p=new Person();
// p.eat();
//1.加载配置文件
//1.1 创建Propertires对象
Properties pro=new Properties();
//1.2 加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件 可以用 类加载器
ClassLoader classLoader=ReflectTest.class.getClassLoader();
//classLoader.getResource();//获取资源的路径
//获取资源的字节流
InputStream is=classLoader.getResourceAsStream("pro.properties");
pro.load(is);
// is.close();
//2.获取配置文件中定义的数据
String className=pro.getProperty("String");
String methodName=pro.getProperty("methodName");
//3.加载该类进内存
Class cls=Class.forName(className);
//4.创建对象
Object obj=cls.newInstance();
//5.获取方法对象
Method method=cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
* Field:成员变量
*操作:
1.设置值
*void set(Object obj,Object value)
2.获取值
*get(Object obj)
3.忽略访问权限修饰符的安全检查
* setAccessible(true):暴力反射
* Constructor:构造方法
*创建对象:
* T newInstance(Object...initargs)
* 如果使用空参数操作对象,是可以简化的:
Class对象的newInstance方法
* Method: 方法对象
*执行方法:
* Object invole(Object objmObject...args)
*获取方法名称
* String getName():获取方法名
* 案例:
*需求:写一个“框架”,不改变该类的任何代码前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
*实现:
1.配置文件
2.反射
*步骤:
1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置文件
3.使用反射技术加载类文件进内存
4.创建对象
5.执行方法