反射给人的第一感觉:
常规调用是obj.field. / obj.method()
反射则是field.get(obj). / method.invoke(obj) 执行的主体发生了变化,非常适合于对象未定义的场景下,例如框架等通用场景。反射的定义:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为JAVA语言的反射机制。
反射的API:
// Class类 Constructor类@Testpublic void demo1() throws Exception { // Class.forName(String class). 用于加载类的.class文件并封装为Class对象 Class class1 = Class.forName("com.imooc.reflect.test.Person"); // 获得无参构造 Constructor c = class1.getConstructor(); // 实例化对象 返回Object Person person = (Person)c.newInstance(); person.eat();}@Testpublic void demo2() throws Exception{ Class class2 = Class.forName("com.imooc.reflect.test.Person”); // 获得带参构造 Constructor c = class2.getConstructor(String.class, String.class); Person person = (Person)c.newInstance("张三","男"); person.eat();}
// Field类@Testpublic void demo1() throws Exception{ Class class1 = Class.forName("com.imooc.reflect.test.Person"); // 只能获得公有属性 Field field = class1.getField("name"); Person p = (Person)class1.newInstance(); // 设置对象属性值 field.set(p, "李四”); // 获得对象属性值 返回Object Object obj = field.get(p); System.out.println(obj);}@Testpublic void demo2() throws Exception{ Class class1 = Class.forName("com.imooc.reflect.test.Person”); // 获得所有属性,不论公有还是私有 Field field = class1.getDeclaredField("sex"); Person p = (Person)class1.newInstance(); // 私有属性要设置可访问的权限 field.setAccessible(true); field.set(p,"男"); Object obj = field.get(p); System.out.println(obj);}
// Method类@Testpublic void demo1() throws Exception{ Class class1 = Class.forName("com.imooc.reflect.test.Person"); Person p = (Person)class1.newInstance(); // 获得公有方法 Method method = class1.getMethod("eat"); method.invoke(p);}@Testpublic void demo2() throws Exception{ Class class1 = Class.forName("com.imooc.reflect.test.Person"); Person p = (Person)class1.newInstance(); // 获得私有方法 Method method = class1.getDeclaredMethod("run”); // 私有方法执行前要设置权限 method.setAccessible(true); method.invoke(p);}@Testpublic void demo3() throws Exception{ Class class1 = Class.forName("com.imooc.reflect.test.Person"); Person p = (Person)class1.newInstance(); // 获得私有带参方法 Method method = class1.getDeclaredMethod("hello", String.class); method.setAccessible(true); System.out.println(method.invoke(p, "张三"));}
思考:为什么要有反射机制?
JAVA是一个完全面向对象的语言,但对象往往是个性的,围绕着对象展开的代码也是个性的(对象代码),逻辑上有个性就会有共性,那如果要实现一些共性的场景比如框架,该怎么办?
共性的代码需要围绕着共性的实体展开,比如Class对象、Constructor对象、Field对象、Method对象,所有的类都具备这四种实体,所以这些是共性的。在共性的场景中,Class、Constructor等是行为主体,而个性的对象实例则成为行为客体,这是反射中的一个反转点。 除了行为主体不同,共性场景的实现还要求有足够的权限。由于个性实例是复杂多样的,共性代码想要包罗万象必然需要被授权访问这些实例的所有内容,这是反射的另一个要点。 有时我们觉得有了反射机制那封装和访问修饰符还有什么用吗?在我看来由于对象代码和反射机制针对的场景不同,所以不存在冲突。如果硬要在对象代码中使用反射,那可能是代码编写者出现了问题。