一,反射的使用场景
1,java程序中许多对象在运行时会出现两种状态:编译时类型和运行时类型如:
Person p=new Student();
在执行时会执行子类的方法,即其中编译时类型为Person,运行时类型会变为Student
2,可以降低程序间的耦合度
3,java中的动态化
二,反射API
1,Class类:类
2,Field类:字段
3,Method类:方法
4,Constructor类:构造器
三,反射使用步骤
获取想要操作的类的Class对象(new出来的是实例对象,我们要获得Class对象)->使用反射api操作这些信息->使用反射调用方法
1,获取Class对象
1>通过调用某个对象的getClass()方法
//获取类的实例对象
Fruit fruit=new Fruit();
//获取Class对象
Class fruitClass=fruit.getClass();
2>调用某个类的class属性获取该类的Class对象
//2,通过类名获取
Class clazz=Fruit.class;
3>使用Class类中的forName()静态方法(最安全,性能最好)
Class forName=Class.forName("com.reflection.Fruit");
2,使用反射api操作这些信息
1>获取构造函数API(四种)
//获取class对象
Class clazz=Class.forName("com.reflection.Fruit");
//1,根据指定参数获取public构造器
Constructor constructor=clazz.getConstructor(String.class,double.class);
System.out.println(constructor);
//2,获取所有public构造器放入Constructor[]数组中
Constructor[] constructors=clazz.getConstructors();
//遍历数组
for(Constructor constructor1:constructors){
System.out.println(constructor1);
}
//3,根据指定参数获取public和非public构造器
Constructor declaredConstructor=clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
//4,获取所有public和非public构造器放入Constructor[]数组中
Constructor[] declaredConstructors=clazz.getDeclaredConstructors();
//遍历数组
for(Constructor declaredConstructor1:declaredConstructors){
2>获取类方法API(四种)
//获取类的class对象
Class clazz = Class.forName("com.reflection.Fruit");
//1,根据方法名和方法参数获取public方法,第一个参数为方法名,第二个为参数类型class对象
Method method = clazz.getMethod("changeColor");
System.out.println(method.toString());
//2,获取所有public方法
Method[] methods = clazz.getMethods();
for (Method method1 : methods) {
System.out.println(method1.toString());
}
//3,根据方法名和方法参数获取public和非public方法
Method method2= clazz.getDeclaredMethod("changeType", String.class);
System.out.println(method2.toString());
//4,获取所有public和非public方法
Method[] methods1= clazz.getDeclaredMethods();
3>获取Field字段变量(同上四种)
分别为:
getField(String name)//根据名称获取public变量
getFields()//获取所有public变量,返回Field[]数组
getDeclaredField(String name)//根据名称获取public和非public变量
getDeclaredFields()//获取所有public和非public变量
3,使用反射调用方法
1>method.invoke(“要调用的方法的名字所属的对象实体(就是方法所属对象实体)”,方法的参数值)
2>如何使用反射创建对象
★使用Class对象的newInstance()方法来创建该class对象对应的类实体,此方法要求该class对象对应的类有默认的空构造器
★先通过class对象获取指定的Constructor对象,再通过Constructor对象的newInstance()方法来创建class对象对用的类实体,可以选定任意构造器
//原始方法
Fruit fruit=new Fruit();
//反射方法1
Class clazz=Class.forName("com.reflection.Fruit");
Fruit fruit1=(Fruit) clazz.newInstance();
fruit1.setName("西瓜");
fruit1.setPrice(23.5);
System.out.println(fruit1.toString());
//反射方法2
Constructor constructor=clazz.getConstructor(String.class,double.class);
Fruit fruit2=(Fruit) constructor.newInstance("西瓜",23.5);
System.out.println(fruit2.toString());
3>反射调用方法
//反射调用方法
Class clazz=Class.forName("com.reflection.Fruit");
//获取方法对象
Method method=clazz.getMethod("changeColor");
//获取changeColor方法所在的实体对象
Fruit fruit=(Fruit) clazz.newInstance();
method.invoke(fruit);
四,反射优缺点
优点:
提高了java程序的灵活性和扩展性,降低了耦合性
缺点:
1,性能比普通方法低,一般用在扩展性和灵活性高的框架上,一般程序不建议使用
2,会破快java封装特性和代码结构,反射代码比一般代码更加复杂,不宜于维护