反射
类加载器
ClassLoader:负责加载类的对象
Java运行时的内置类加载器
Bootstrap class loader 虚拟机的内置类加载器
Platform class loader:平台类加载器
System class loader:应用程序类加载器。
类加载器的继承关系:System的父类加载器为Platform,Platform的父类加载器为Bootstrap
ClassLoader中的两个方法
Static ClassLoader getSystemClassLoader();返回用于委派的系统类加载器
ClassLoader getParent():返回父类加载器进行委派
代码示例:
//返回用于委派的系统类加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //返回父类加载器进行委派 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); ClassLoader parent1 = parent.getParent(); System.out.println(parent1);//null
反射:框架设计的灵魂
在程序运行期间,不引用类,直接调用类的方法
框架:半成品的软件,可以在框架的基础上进行软件的开发,简化编码
反射:将类的组成部分封装成method、field、constructor等对象,这就是反射机制
好处:
在程序的运行过程中操作这些对象
可以解耦,提高程序的可扩展性
获取class类的对象
Class.forName(“全类名”):将字节码文件加载到内存中,返回class地偶像(灵活性高,可以放到配置文件中)。
类名.class:通过类名的class属性获取(最方便)。
对象.getclass():getchass()方法在object类中定义着。
对象.getName(): 获取类名
代码示例:
//使用类的class属性获取 Class<Student> studentClass = Student.class; System.out.println(studentClass); //调用对象的getclass()方法获取 Student st=new Student(); Class<? extends Student> aClass = st.getClass(); System.out.println(aClass==studentClass); //使用class类中的静态方法forname()获取 try { Class<?> aClass1 = Class.forName("Demo02.Student"); System.out.println( aClass1==studentClass); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
反射获取构造方法并使用
getConstructors() 获取所有公共的构造函数
getDeclaredConstructors() 获取所有构造函数
getConstructor() 根据传入参数获取构造函数
newInstance() 创建构造函数的对象
代码示例1:
try { //获取class对象 Class<?> aClass = Class.forName("Demo02.Student"); //获取所有公共的构造函数 //Constructor<?>[] constructors = aClass.getConstructors(); //获取所有构造函数 Constructor<?>[] constructors = aClass.getDeclaredConstructors(); for (Constructor con : constructors) { System.out.println(con); } //获取无参构造函数 getConstructor中可以传入参数 Constructor<?> constructor = aClass.getConstructor(); System.out.println("获取无参构造函数:"+constructor); //创建无参构造函数的对象 Object stu = constructor.newInstance(); System.out.println(stu); } catch(Exception ex) {}
代码示例2:带参数的构造函数
try { Class<?> aClass = Class.forName("Demo02.Student"); Constructor<?> constructor = aClass.getConstructor(String.class, int.class, String.class); Object stu = constructor.newInstance("查理芒格", 98, "奥马哈"); System.out.println(stu); } catch (Exception e) { throw new RuntimeException(e); }
代码示例3:反射私有的构造函数
try { Class<?> aClass = Class.forName("Demo02.Student"); Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class); //暴力反射 私有的也可以反射 declaredConstructor.setAccessible(true); Object stu = declaredConstructor.newInstance("查理芒格"); System.out.println(stu); } catch (Exception ex) { throw new RuntimeException(ex); }
反射获取成员变量并使用
获取所有公共字段 getFields()
获取所有字段 getDeclaredFields()
获取单个字段 getField();
给成员变量赋值 set(Object, Value);
获取成员变量的值 get(Object);
代码示例:
try { Class<?> aClass = Class.forName("Demo02.Student"); //获取所有公共字段 Field[] fields = aClass.getFields(); //获取所有字段 Field[] declaredFields = aClass.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field); } //获取单个字段 Field address = aClass.getField("address"); System.out.println(address); //创建构造函数 Constructor<?> constructor = aClass.getConstructor(); //创建对象 Object stu = constructor.newInstance(); //给成员变量赋值 address.set(stu, "西平"); System.out.println(stu); } catch (Exception e) { throw new RuntimeException(e); }
代码示例2:
try { Class<?> aClass = Class.forName("Demo02.Student"); Constructor<?> constructor = aClass.getConstructor(); Object stu = constructor.newInstance(); System.out.println(stu); Field name = aClass.getDeclaredField("name"); name.setAccessible(true);//设置强制可访问 name.set(stu, "查理芒格"); Field age = aClass.getDeclaredField("age"); age.setAccessible(true);//忽略访问修饰符的安全性检查 age.set(stu, 98); Field address = aClass.getDeclaredField("address"); address.setAccessible(true); address.set(stu, "奥马哈"); System.out.println(stu); } catch (Exception e) { throw new RuntimeException(e); }
反射获取成员方法并使用
获取所有公有方法,包括继承的方法 getMethods();
获取所有本类的方法,包括私有方法 getDeclaredMethods();
获取单个方法对象 getDeclaredMethod("method1");
获取方法名 method.getName()
调用方法 method.invoke(object);
代码示例:
try { Class<?> aClass = Class.forName("Demo02.Student"); Constructor<?> constructor = aClass.getConstructor(); Object stu = constructor.newInstance(); //获取所有公有方法,包括继承的方法 Method[] methods = aClass.getMethods(); //获取所有本类的方法,包括私有方法 Method[] declaredMethods = aClass.getDeclaredMethods(); for (Method me : declaredMethods) { System.out.println(me); } //获取单个方法对象 Method method1 = aClass.getDeclaredMethod("method1"); //调用方法 method1.invoke(stu); } catch (Exception e) { throw new RuntimeException(e); }
代码示例2:
try { Class<?> aClass = Class.forName("Demo02.Student"); Constructor<?> constructor = aClass.getConstructor(); Object stu = constructor.newInstance(); Method function = aClass.getDeclaredMethod("function"); function.setAccessible(true); function.invoke(stu); Method method1 = aClass.getMethod("method1"); method1.invoke(stu); //获取带参方法对象 Method method2 = aClass.getMethod("method2", String.class); //调用带参方法 method2.invoke(stu,"查理芒格"); Method method3 = aClass.getMethod("method3", String.class, int.class); //调用带返回参数对象 Object o = method3.invoke(stu, "查理芒格", 98); System.out.println(o); } catch (Exception e) { throw new RuntimeException(e); }
运行配置文件指定内容反射
代码示例1:
try { //加载配置文件中的数据到集合中 Properties pro = new Properties(); FileReader fr = new FileReader("F:\\学习\\02 JAVA\\Code\\01JavaBase\\myReflect\\src\\myclass.txt"); pro.load(fr); fr.close(); //获取集合中的类和方法 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); Class<?> aClass = Class.forName(className); Constructor<?> className1 = aClass.getConstructor(); Object obj = className1.newInstance(); //调用类中的方法 Method methodName1 = aClass.getMethod(methodName); methodName1.invoke(obj); } catch (Exception ex) { throw new RuntimeException(ex); }
配置文件myclass.txt节点如下:
className=Demo06.Teacher
methodName=teach
代码示例2:
注意:需要在src下创建一个名字为pro.properties的File文件
/* 根据配置文件反射创建类对象,并执行方法 * */ try { Properties pro = new Properties(); //使用类加载方式,获取class目录下的配置文件 ClassLoader classLoader = ReflectDemo01.class.getClassLoader(); InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties"); //加载配置文件中的数据到集合中 pro.load(resourceAsStream); //获取配置文件中定义的数据 String classname=pro.getProperty("className"); String method=pro.getProperty("methodName"); //根据配置文件中的类和方法创建对象,调用方法 Class<?> aClass = Class.forName(classname); Constructor<?> classname1 = aClass.getConstructor(); Object obj = classname1.newInstance(); Method method1 = aClass.getMethod(method); method1.invoke(obj); } catch(Exception ex) { throw new RuntimeException(ex); }