1 什么是反射?
Reflection(反射) 是 Java 程序开发语言的特征之一,他允许运行中的Java程序对自身进行检查,
他甚至可以直接操作程序的私有属性,在Java底层,SSM框架底层,使用了大量的反射,反射可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
2 反射需要用到的API
2.1获取字节码对象(三种方式)
Class.forName("类的全路径");
类名.class; 例如Student.class
对象.getClass(); 例如 new Student().getClass();
2.2 常用方法
例子:
Fswl物料类
package cn.tedu.LX;
public class Fswl {
//1.定义成员变量
public String name;
public int age;
int see;
//2.定义构造方法
//快捷方式:右键-->Source-->倒数第三个-->OK
private String sex;
public Fswl() {}//注意要先手动添加无参构造,防止被覆盖
public Fswl(String name, int age, int see, String sex) {
this.name = name;
this.age = age;
this.see = see;
this.sex = sex;
}
public Fswl(String name, int age) {
super();
this.name = name;
this.age = age;
}
//3.定义成员方法
public void eat(int n) {
System.out.println("饿了吃点火锅吧"+n);
}
private void sleep(int a){
System.out.println("sleep" + a);
}
//4.提供重写的toString()
//目的:为了方便查看对象的属性值
@Override
public String toString() {
return "Student [name="+ name +",age="+ age +"]";
}
}
Fs实现类
package cn.tedu.LX;
import javax.sound.midi.Soundbank;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Fs {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.tedu.LX.Fswl");
System.out.println(clazz.getPackage());//package + 包名 package cn.tedu.LX
System.out.println(clazz.getPackage().getName()); //包名 cn.tedu.LX
System.out.println(clazz.getSimpleName());//类名 Fswl
System.out.println(clazz.getName()); //完整类名 cn.tedu.LX.Fswl
//获得完整的公共属性路径, 包括继承的变量 用默认来修饰属性,也获取不到,
Field[] fields = clazz.getFields();
System.out.println(Arrays.toString(fields));
for(Field data:fields){
System.out.println(data.getType().getName());
}
// 通过暴力反射获得类中的所有的属性 包括私有,默认 ,但不包括检查的变量
Field[] dfs = clazz.getDeclaredFields();
System.out.println(Arrays.toString(dfs));
/*for(Field data:dfs){
System.out.println(data.getType().getName());
}*/
//获取所有的公开的构造方法
Constructor<?>[] constructors = clazz.getConstructors();
for(Constructor<?> data:constructors){
System.out.println(data.getName());
}
//获取所有的构造方法,包括私有 暴力反射
Constructor<?>[] constructors1 = clazz.getDeclaredConstructors();
for(Constructor<?> data:constructors1){
System.out.println(data.getName());
}
//获取所有可见的方法,包括继承的方法
Method[] methods = clazz.getMethods();
for(Method data:methods){
System.out.println(data.getName());
}
System.out.println("================");
//暴力反射,获得所有的方法,包括私有,不包括继承的方法
Method[] methods1 = clazz.getDeclaredMethods();
for(Method data:methods1){
System.out.println(data.getName());
}
/* 反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法
反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法*/
//创建对象 触发无参构造
System.out.println("==========");
Object o = clazz.newInstance();
System.out.println(o);
//创建对象 触发指定属性的构造方法
System.out.println("==========");
//因为方法参数列表是String,int 是private 私有的的
Constructor<?> c1 = clazz.getConstructor(String.class, int.class);
Object o1 = c1.newInstance("海绵宝宝", 20);
System.out.println(o1);
System.out.println("==========");
//子类可以随便使用父类的方法,属性,而父类要想使用子类的方法,属性,要向下转型,要把父类强制转成指定的子类类型
Fswl s = (Fswl)o1;
System.out.println(s.name);
System.out.println(s.age);
s.eat(666);
System.out.println("==========");
//暴力反射
Class<?> clazz1 = Class.forName("cn.tedu.LX.Fswl");
//获取私有属性
Field sex = clazz1.getDeclaredField("sex");
//查看私有属性的类型
System.out.println(sex.getType());//class java.lang.String
System.out.println(sex.getType().getName());//java.lang.String
//4 设置属性的值
//4.1 没有对象就通过反射来创建对象
Object o2 = clazz1.newInstance();
//4.2 暴力反射,需要设置西游可见
sex.setAccessible(true);
//4.3通过字段对象来给刚刚创建的对象obj设置name属性值为“派大星”
//set(m,n)-- m:要给哪个对象设置属性值,n:是要设置的属性的具体值
sex.set(o2,"男");
//4.4通过字段对象获取刚刚给obj对象设置的私有属性的值
System.out.println(sex.get(o2));
System.out.println("==========");
//暴力反射获取和设置私有方法*/
/*getDeclaredMethod(m,x,y,z...)
* m:要获取的方法名
* x,y,z...可变参数,是这个方法的参数类型,但注意要加“.class”
* */
Method sleep = clazz1.getDeclaredMethod("sleep",int.class);
sleep.setAccessible(true);
/*invoke(o,x,y,z...),表示通过反射技术执行方法
* o :要执行的是哪个对象的方法
* x,y,z...:执行这个方法【method对象代表的之前获取到的save()】时需要传入的参数
* */
sleep.invoke(o2,20);
}
}