反射
反射:框架设计的灵魂
名词解释: * 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码 * 反射:将类的各个组成部分封装为其他对象,这就是反射机制
使用反射优点: 1. 可以在程序运行过程中,操作这些对象。 2. 可以解耦,提高程序的可扩展性。
获取Class对象的方式
1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象 * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类 2. 类名.class:通过类名的属性class获取 * 多用于参数的传递 3. 对象.getClass():getClass()方法在Object类中定义着。 * 多用于对象的获取字节码的方式
三种方式获取Class对象代码
1 package demo14.reflect; 2 3 public class demo01 { 4 public static void main(String[] args) throws ClassNotFoundException { 5 // 1 Class.forName("全类名") 6 Class aClass = Class.forName("demo14.reflect.Person"); 7 System.out.println(aClass); 8 9 // 2 类名.class 10 Class bClass = Person.class; 11 System.out.println(bClass); 12 13 // 3 对象.getClass() 14 Person person = new Person(); 15 Class cClass = person.getClass(); 16 System.out.println(cClass); 17 18 //检查三种方式获取的Class对象是否一致 19 System.out.println(aClass == bClass); 20 System.out.println(bClass == cClass); 21 22 } 23 }
执行结果
# 注:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
Class对象功能
1. 获取成员变量们 * Field[] getFields() :获取所有public修饰的成员变量 * Field getField(String name) 获取指定名称的 public修饰的成员变量 * Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符 * Field getDeclaredField(String name) 2. 获取构造方法们 * Constructor<?>[] getConstructors() * Constructor<T> getConstructor(类<?>... parameterTypes) * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) * Constructor<?>[] getDeclaredConstructors() 3. 获取成员方法们: * Method[] getMethods() * Method getMethod(String name, 类<?>... parameterTypes) * Method[] getDeclaredMethods() * Method getDeclaredMethod(String name, 类<?>... parameterTypes) 4. 获取全类名 * String getName()
Field:成员变量 * 操作: 1. 设置值 * void set(Object obj, Object value) 2. 获取值 * get(Object obj) 3. 忽略访问权限修饰符的安全检查 * setAccessible(true):暴力反射 Constructor:构造方法 * 创建对象: * T newInstance(Object... initargs) * 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法 Method:方法对象 * 执行方法: * Object invoke(Object obj, Object... args) * 获取方法名称: * String getName:获取方法名
Class对象获取成员变量、对成员变量值进行获取与设置代码示例
1 package demo14.reflect; 2 3 import java.lang.reflect.Field; 4 5 public class demo02 { 6 public static void main(String[] args) throws Exception { 7 /* 8 * Field[] getFields() :获取所有public修饰的成员变量 9 * Field getField(String name) 获取指定名称的 public修饰的成员变量 10 11 * Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符 12 * Field getDeclaredField(String name) 获取指定名称的成员变量 不考虑修饰符 13 */ 14 15 // 1 获取Class对象 16 Class cls = Class.forName("demo14.reflect.Person"); 17 18 // 2 获取成员变量方法 19 // 2.1 获取所有的public修饰的成员变量 20 Field[] fields = cls.getFields(); 21 for (Field field : fields) { 22 System.out.println(field); 23 } 24 // 2.2 获取指定的public修饰的成员变量 25 Field a = cls.getField("a"); 26 System.out.println(a); 27 //2.2.1获取和设置Field值 28 Person person = new Person(); 29 Object o = a.get(person); 30 System.out.println(o); 31 a.set(person, "kelvin"); 32 System.out.println(person); 33 34 // 2.3 获取所有的成员变量 35 Field[] declaredFields = cls.getDeclaredFields(); 36 for (Field field : declaredFields) { 37 System.out.println(field); 38 } 39 40 // 2.4 获取指定的成员变量 41 Field d = cls.getDeclaredField("d"); 42 System.out.println(d); 43 //忽略访问权限修饰符的安全检查(暴力反射) 44 d.setAccessible(true); 45 //2.4.1获取和设置非public修饰的Field值 46 Person person1=new Person(); 47 Object o1 = d.get(person1); 48 System.out.println(o1); 49 d.set(person1,"jack"); 50 System.out.println(person1); 51 } 52 }
Class对象获取构造方法,并根据构造方法创建对象
1 package demo14.reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.util.Arrays; 5 6 public class demo03 { 7 public static void main(String[] args) throws Exception { 8 /* 9 Constructor<?>[] getConstructors() 10 Constructor<T> getConstructor(类<?>... parameterTypes) 11 12 Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 13 Constructor<?>[] getDeclaredConstructors() 14 15 创建对象: 16 T newInstance(Object... initargs) 17 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法 18 19 */ 20 21 Class cls = Class.forName("demo14.reflect.Person"); 22 // 1 获取所有public修饰的构造方法 23 Constructor[] constructors = cls.getConstructors(); 24 System.out.println(Arrays.toString(constructors)); 25 26 // 2 获取指定的参数的构造方法 27 Constructor constructor = cls.getConstructor(String.class, int.class); 28 System.out.println(constructor); 29 // 2.1 使用有参构造方法创建对象 30 Object kelvin = constructor.newInstance("kelvin", 23); 31 System.out.println(kelvin); 32 33 // 3 获取无参构造方法 34 Constructor constructor1 = cls.getConstructor(); 35 System.out.println(constructor1); 36 // 3.1 使用无参构造方法创建对象 37 // 方式一 38 Object o = constructor1.newInstance(); 39 System.out.println(o); 40 // 方式二 41 Object o1 = cls.newInstance(); 42 System.out.println(o1); 43 44 45 } 46 }
Class获取成员方法并执行
1 package demo14.reflect; 2 3 import java.lang.reflect.Method; 4 import java.util.Arrays; 5 6 public class demo04 { 7 public static void main(String[] args) throws Exception { 8 /* 9 Method[] getMethods() 10 Method getMethod(String name, 类<?>... parameterTypes) 11 12 Method[] getDeclaredMethods() 13 Method getDeclaredMethod(String name, 类<?>... parameterTypes) 14 15 执行方法: 16 Object invoke(Object obj, Object... args) 17 获取方法名称: 18 String getName:获取方法名 19 20 */ 21 Class cls = Class.forName("demo14.reflect.Person"); 22 23 // 1 获取所有的public成员方法 24 Method[] methods = cls.getMethods(); 25 System.out.println(Arrays.toString(methods)); 26 // 2 获取指定的public成员带参方法 27 Person person = new Person(); 28 Method run = cls.getMethod("run", String.class); 29 run.invoke(person, "kelvin"); 30 // 3 获取指定的public修饰无参成员方法 31 Method run1 = cls.getMethod("run"); 32 run1.invoke(person); 33 34 // 4 获取private修饰的成员方法 35 Method eat = cls.getDeclaredMethod("eat"); 36 // 暴力反射 37 eat.setAccessible(true); 38 eat.invoke(person); 39 } 40 }
反射应用实例
借助配置文件,配置文件可以配置类和方法。
1 package demo14.reflect; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.lang.reflect.Method; 6 import java.util.Properties; 7 8 public class demotest { 9 /* 10 不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法 11 */ 12 public static void main(String[] args) throws Exception { 13 Properties pro = new Properties(); 14 15 ClassLoader classLoader = demotest.class.getClassLoader(); 16 InputStream resourceAsStream = classLoader.getResourceAsStream("demo14/reflect/pro.properties"); 17 pro.load(resourceAsStream); 18 19 String className = pro.getProperty("className"); 20 String classMethod = pro.getProperty("classMethod"); 21 22 Class cls = Class.forName(className); 23 Method method = cls.getMethod(classMethod); 24 25 Object o = cls.newInstance(); 26 method.invoke(o); 27 } 28 }
配置文件
className=demo14.reflect.Student
classMethod=study
反射图解