1.反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
2.获取class文件对象的三种方式
1 object类的getclass()方法,判断两个对象是否是同一个字节码文件
2 静态属性class,锁对象
3 class类中静态方法forname(),读取配置文件
读取配置文件并用反射创建对象
package javastudy02;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class reflect {
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
BufferedReader br = new BufferedReader(new FileReader("src/config.properties"));
Class clazz = Class.forName(br.readLine());
fruit f = (fruit) clazz.newInstance();
f.run();
}
}
public class fruit {
public void run(){
System.out.println("水果类中的方法");
}
}
//还有cinfig.properties配置文件
通过反射获取带参构造方法
package javastudy02;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class reflect2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//class的newinstance()方法是通过该类的无参构造函数创建对象,如果一个类没有无参构造,就需要调用
//getconstructor
Class clazz = Class.forName("javastudy02.person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造
person p = (person) c.newInstance("张三",22);
System.out.println(p);
}
}
package javastudy02;
public class person {
public person(String name,int age){
System.out.println("["+name+":"+age+"]");
}
}
运行结果
通过反射获取成员变量并使用
package javastudy02;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class reflect2 {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("javastudy02.person");
Constructor c = clazz.getConstructor(String.class,int.class);
person p = (person) c.newInstance("张三",22);
//这里与上面一样,是从clazz中获取字段
Field f = clazz.getDeclaredField("name");
f.setAccessible(true); //这里是暴利方法,没有设置私有的字段只需要getfield方法获取再set即可
f.set(p,"李四");
System.out.println(p);
}
}
通过反射获取方法并使用
package javastudy02;
public class person {
String name ;
private int age ;
public person( String name, int age){
System.out.println("["+name+":"+age+"]");
}
public void number(int number){
System.out.println("这是数字"+number);
}
}
package javastudy02;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect2 {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("javastudy02.person");
Constructor c = clazz.getConstructor(String.class,int.class);
person p = (person) c.newInstance("张三",22);
Method m = clazz.getMethod("number", int.class);//获取方法,且参数类型int要写成int.class字节码
m.invoke(p, 3);
}
}
运行结果
通过反射越过泛型检查
目标案例:ArrayList<integer>的一个对象,怎么在这个集合中添加一个字符串数据
package javastudy02;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class arra {
public static void main(String[] args) throws Exception {
// 泛型只在编译期有效,在运行期会被擦除(变成.class后)
ArrayList<Integer> list = new ArrayList<>();
list.add(111);
Class clazz = Class.forName("java.util.ArrayList"); //获取字节码文件
Method m = clazz.getMethod("add",Object.class); //获取add方法
m.invoke(list,"abc");
System.out.println(list);
}
}
运行结果
通过反射写一个通用的设置某个对象的某个属性为指定值
package javastudy02;
import java.lang.reflect.Field;
public class tool {
//将OBJ的对象中的propertyname属性的值设置为value
public void setproperty(Object object,String properyname,Object value) throws Exception {
Class clazz = object.getClass(); //反射获取字节码
Field f = clazz.getDeclaredField(properyname); // 反射获取字段
f.setAccessible(true);
f.set(object, value);
}
}
package javastudy02;
public class person1 {
private String name ;
private int age ;
public person1(){
super();
}
public person1(String name, int age) {
super();
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "person1 [name=" + name + ", age=" + age + "]";
}
}
package javastudy02;
public class tooltest {
public static void main(String[] args) throws Exception {
person1 p = new person1("张三",23);
System.out.println(p);
new tool().setproperty(p,"name","李四");
System.out.println(p);
}
}
运行结果