java之反射
反射:
当一个字节码文件加载到内存的时候,jvm会对该字节码进行解剖,然后会创建一个对象的Class对象,把字节码文件的信息全部都
存储到该Class对象中,我们只要获取到Class对象,我们就可以使用字节码对象设置对象的属性或者调用对象的方法等操作....
注意: 在反射技术中一个类的任何成员都有对应 的类进行描述。 比如: 成员变量(Field) 方法----> Method类
例如图:
Person的字节码进入到方法区中,会创建一个对应的Class对象,这个对象包含字节码的所有内容
1、获取Class对象的三种方法:
1 //推荐使用: 获取Class对象的方式一,通过完整的类名 2 Class clazz1 = Class.forName("cn.itcast.reflect.Person"); 3 System.out.println("clazz1:"+ clazz1); 4 5 6 //获取Class对象的方式二: 通过类名获取 7 Class clazz2 = Person.class; 8 System.out.println("clazz1==clazz2?"+ (clazz1==clazz2)); 9 10 11 //获取Class对象的方式三 :通过对象获取 12 Class clazz3 = new Person(110,"狗娃").getClass(); 13 System.out.println("clazz2==clazz3?"+ (clazz2==clazz3));
三者Class获取是相同的
2、通过反射获取一个类的构造方法
Constructor
当构造方法为public,所有构造函数时
//通过Class对象获取对应的构造方法 Constructor[] constructors = clazz.getConstructors(); // getConstructors()获取一个类的所有公共的构造方法 for(Constructor constructor : constructors){ System.out.println(constructor); }
获取单个构造函数
Constructor constructor = clazz.getConstructor(int.class,String.class); // getConstructor 获取单个指定的构造方法。 Person p = (Person) constructor.newInstance(999,"小城"); // newInstance()创建一个对象 System.out.println(p);
获取公共和私有的构造函数
Constructor[] constructors = clazz.getDeclaredConstructors(); //获取到一个类的所有构造方法,包括私有的在内 。 for(Constructor constructor : constructors){ System.out.println(constructor); }
获取单个构造函数(包括私有)
//获取私有的构造函数 Constructor constructor = clazz.getDeclaredConstructor(null);
根据构造方法创建对象(如果获取的构造函数为私有的话,则就使用下面获取,不为私有就简化)
//获取私有的构造函数 Constructor constructor = clazz.getDeclaredConstructor(null); //暴力反射 constructor.setAccessible(true);//设置访问权限 Person p =(Person) constructor.newInstance(null); System.out.println(p);
3、获取方法
Method
获取所有的公共方法
//获取到对应的Class对象 Class clazz = Class.forName("cn.itcast.reflect.Person"); //获取到所有公共的方法 Method[] methods = clazz.getMethods(); // getMethods() 获取所有 的公共方法而已还包含从父类继承的方法。
获取所有方法
Method[] methods = clazz.getDeclaredMethods(); //获取到所有的方法,但是不包含父类的方法。
执行方法:
a、公共非静态
Person p = new Person(110,"狗娃"); Method m = clazz.getMethod("eat", int.class);//是一个是方法名,第二个为参数名(没有填写null) m.invoke(p, 3); //invoke 执行一个方法。 第一个参数:方法的调用对象。 第二参数: 方法所需要的参数
b、公共静态
Method m = clazz.getMethod("eat", int.class); m.invoke(null, 3); //invoke 执行一个方法。 第一个参数:方法的调用对象。 第二参数: 方法所需要的参数。
c、数组参数时
Method m = clazz.getMethod("sum", int[].class); m.invoke(p,new int[]{12,5,9});
d、私有方法
//执行私有的方法 Method m =clazz.getDeclaredMethod("sleep",int.class); //设置访问权限允许访问 m.setAccessible(true); m.invoke(null, 6);
4、获取成员变量
Field
//获取到对应的Class对象 Class clazz = Class.forName("cn.itcast.reflect.Person"); //获取 到所有的成员变量 /*Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ System.out.println(field); }*/ Person p = new Person(); Field field = clazz.getDeclaredField("id");//获取私有的成员变量时,要设置访问权限 //设置访问权限可以访问 field.setAccessible(true); field.set(p, 110); //第一个参数: 设置该数据 的成员变量, 第二个参数:属性值。 System.out.println(p);