我所知的反射
一、反射的概述
1.反射的介绍:
Java的反射机制是在运行的状态中,对于任意的一个类,能够知道这个类的所有属性和方法;对于任意一个对象,能够调用它的任意一个属性和方法,这种动态获取的信息以及动态调用对象的方法的功能成为java语言的反射机制
一句话,反射技术可以对类进行解剖。
2. 反射中涉及的概念:
Java中的.class文件是java的可运行文件,叫字节码文件,java的.class文件也有共性,可以单独抽取出来,用“类”来描述。这个“类”就是Class(注意这是类的名字)。
要想获取一个类的内容,必须先要获取这个类所在的字节码文件对象,该对象是Class类型
字节码文件对象的作用:New一个Person对象,首先加载Person.class文件进内存,进内存时就被封装成了对象
例:Person类
public class Person {
//成员变量
public String sex;
private String name;
private int age;
//构造方法
public Person(){
System.out.println("Person 构造方法运行");
}
//重载的方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//静态方法
public static void show(){
System.out.println("show静态方法执行");
}
//带参数的方法
public String eate(String a,int b){
String res = a + b;
System.out.println("function param:"+ a + "." + b);
return res;
}
//私有方法
private void joke(){
System.out.println("joke私有方法执行");
}
//不带参数的方法
public void run(){
System.out.println("run普通方法执行");
}
}
二、字节码文件对象的获取的三种方法
1、通过对象获取 getclass();
Person p = new Person();
Class class1 = p.getClass();
2、通过类型获取 .class()
Class class2 = Person.class;
3、通过字符串获取 forName();
Class class3 = Class.forName("fanshe.Person");//全限定类名
三、获取自解码文件对象中的字段
getDeclaredField是可以获取一个类本身的所有字段,包括private
getField只能获取类及其父类的public 字段
//字符串获取自解码文件对象(以字符串获取为例)
Class class1 = Class.forName("fanshe.Person");
//获取字节码文件中的字段
Field[] declaredFields = class1.getDeclaredFields(); //获取到该类所有字段,不包括继承的需要遍历
Field declaredField = class1.getDeclaredField("name"); //获取到该类单个字段
Field[] fields = class1.getFields(); //获取到该类及其父类所有公共字段
Field field = class1.getField("name"); //获取到该类公共单个字段
//给字段赋值
Field field = class1.getDeclaredField("name");
Object obj = class1.newInstance();
field.setAccessible(true); //私有字段要写这句,跳过权限检查
field.set(obj, "小红"); //字段赋值
Object value = field.get(obj); //获取字段值并接收
四、获取自解码文件对象中的方法
public Method[] getMethods():返回某个类的所有公用(public)方法和其父类的公用方法,也包括它所实现接口的方法。
public Method[] getDeclaredMethods():返回某个类的所有方法,包括私有方法,也包括它所实现接口的方法,但不包括继承的方法。
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数。 要求被调用的构造函数是可见的,也即必须是public类型的;
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。在特定的情况下,可以调用私有的构造函数。
//字符串获取自解码文件对象(字符串获取)
Class class1 = Class.forName("fanshe.Person");
1、//获取所有方法
Method[] methods = class1.getMethods();
Method[] declaremethods = class1.getDeclaredMethods();
2、//获取构造方法
Object object = class1.newInstance();
3、//给带参数的构造方法赋值
赋值要用到Constructor了,预先遍历出构造方法的参数是什么类型,括号里写类型.class
Constructor constructor = class1.getConstructor(String.class,int.class);
Object object = constructor.newInstance("小明",18);
4、//获取不带参数的普通方法(run方法没有参数所以写null)
Method method = class1.getDeclaredMethod("run", null);
//将该方法反射到对象上,该方法的返回值是什么就用什么接
Object obj= class1.newInstance();
method.invoke(obj, null);
5、//获取带参数的普通方法
Method method = class1.getMethod("eate", String.class,int.class);
Object obj = class1.newInstance();
Object reValue = method.invoke(obj, "小刚",30);
6、//获取静态方法
Method method = class1.getMethod("show", null);
method.invoke(null, null);
7、//获取私有方法
Method method = class1.getDeclaredMethod("privateShow", null);
method.setAccessible(true); //跳过权限检查
Object obj= class1.newInstance();
method.invoke(obj, null);
五、 反射的应用案例
接口USB:

实现类USBMouse:

实现类USBKeyBoard:

配置文件UsbTool(新建file文件):

业务逻辑Computer类:

主方法,测试方法:

运行输出的是“键盘启动”,改变配置文件usb = fanshe.UsbMouse,输出的就是“鼠标启动”,这样就可以在不改变代码的情况下变更需求,实现耦合。

浙公网安备 33010602011771号