反射
反射: 当一个字节码文件加载到内存的时候,jvm会对该字节码进行解剖,然后会创建一个对象的Class对象,把字节码文件的信息全部都
存储到该Class对象中,我们只要获取到Class对象,我们就可以使用字节码对象设置对象的属性或者调用对象的方法等操作....
注意: 在反射技术中一个类的任何成员都有对应 的类进行描述。 比如: 成员变量(Field) 方法----> Method类
1 public class Demo1 { 2 3 Person p; 4 5 public static void main(String[] args) throws ClassNotFoundException { 6 //Person p = new Person(110,"狗娃"); 7 8 //推荐使用: 获取Class对象的方式一 9 Class clazz1 = Class.forName("cn.itcast.reflect.Person"); 10 System.out.println("clazz1:"+ clazz1); 11 12 //获取Class对象的方式二: 通过类名获取 13 Class clazz2 = Person.class; 14 System.out.println("clazz1==clazz2?"+ (clazz1==clazz2)); 15 16 //获取Class对象的方式三 :通过对象获取 17 Class clazz3 = new Person(110,"狗娃").getClass(); 18 System.out.println("clazz2==clazz3?"+ (clazz2==clazz3)); 19 } 20 }
如何通过Class对象获取构造方法。
1 public class Demo2 { 2 3 public static void main(String[] args) throws Exception { 4 //获取到对应的Class对象 5 Class clazz = Class.forName("cn.itcast.reflect.Person"); 6 7 //通过Class对象获取对应的构造方法 8 /*Constructor[] constructors = clazz.getConstructors(); // getConstructors()获取一个类的所有公共的构造方法 9 for(Constructor constructor : constructors){ 10 System.out.println(constructor); 11 } 12 13 Constructor[] constructors = clazz.getDeclaredConstructors(); //获取到一个类的所有构造方法,包括私有的在内 。 14 for(Constructor constructor : constructors){ 15 System.out.println(constructor); 16 } 17 */ 18 19 /*Constructor constructor = clazz.getConstructor(int.class,String.class); // getConstructor 获取单个指定的构造方法。 20 Person p = (Person) constructor.newInstance(999,"小城"); // newInstance()创建一个对象 21 System.out.println(p);*/ 22 23 //获取私有的构造函数 24 Constructor constructor = clazz.getDeclaredConstructor(null); 25 //暴力反射 26 constructor.setAccessible(true); //强制在外部访问私有的构造方法 27 Person p =(Person) constructor.newInstance(null); 28 System.out.println(p); 29 } 30 } 31 注意:凡是class.getDeclaredXxxxs()将返回所有的包括私有的
反射技术中Method类描述成员方法
1 /* 2 通过Class对象获取到对应的方法。 3 4 在反射技术中使用了Method类描述了方法的。 5 6 */ 7 public class Demo3 { 8 9 public static void main(String[] args) throws Exception { 10 //获取到对应的Class对象 11 Class clazz = Class.forName("cn.itcast.reflect.Person"); 12 //获取到所有公共的方法 13 /*Method[] methods = clazz.getMethods(); // getMethods() 获取所有 的公共方法而已。 14 Method[] methods = clazz.getDeclaredMethods(); //获取到所有的方法,但是不包含父类的方法。 15 for(Method method : methods){ 16 System.out.println(method); 17 }*/ 18 19 Person p = new Person(110,"狗娃"); 20 /* 21 Method m = clazz.getMethod("eat", int.class); 22 m.invoke(p, 3); //invoke 执行一个方法。 第一个参数:方法的调用对象。 第二参数: 方法所需要的参数。 23 24 //执行私有的方法 25 Method m =clazz.getDeclaredMethod("sleep",int.class); 26 //设置访问权限允许访问 27 m.setAccessible(true); 28 m.invoke(null, 6);*/ //调用静态方法 29 30 Method m = clazz.getMethod("sum", int[].class); 31 m.invoke(p,new int[]{12,5,9}); //数组作为参数 32 } 33 }
Field类获取成员变量
1 /* 2 通过反射获取对应的成员变量 3 4 在反射技术中使用了Field类描述了成员变量的。 5 6 */ 7 8 public class Demo4 { 9 10 public static void main(String[] args) throws Exception { 11 //获取到对应的Class对象 12 Class clazz = Class.forName("cn.itcast.reflect.Person"); 13 //获取 到所有的成员变量 14 /*Field[] fields = clazz.getDeclaredFields(); 15 for(Field field : fields){ 16 System.out.println(field); 17 }*/ 18 Person p = new Person(); 19 Field field = clazz.getDeclaredField("id"); 20 //设置访问权限可以访问 针对私有属性 21 field.setAccessible(true); 22 field.set(p, 110); //第一个参数: 设置该数据 的成员变量, 第二个参数:属性值。 23 System.out.println(p); 24 } 25 }