今日内容介绍
一、类加载器
二、反射构造方法
三、反射成员变量
四、反射成员方法
五、反射配置文件运行类中的方法java
当程序要使用某个类时,若是该类还未被加载到内存中,则系统会经过加载,链接,初始化三步来实现对这个类进行初始化。 * a 加载 * 就是指将class文件读入内存,并为之建立一个Class对象。 * 任何类被使用时系统都会创建一个Class对象 * b 链接 * 验证 是否有正确的内部结构,并和其余类协调一致 * 准备 负责为类的静态成员分配内存,并设置默认初始化值 * 解析 将类的二进制数据中的符号引用替换为直接引用 * c 初始化 * 就是咱们之前讲过的初始化步骤(new 对象) * 注:简单的说就是:把.class文件加载到内存里,并把这个.class文件封装成一个Class类型的对象。
如下的状况,会加载这个类。 * a. 建立类的实例 * b. 类的静态变量,或者为静态变量赋值 * c. 类的静态方法 * d. 使用反射方式来强制建立某个类或接口对应的java.lang.Class对象 * e. 初始化某个类的子类 * f. 直接使用java.exe命令来运行某个主类
负责将.class文件加载到内在中,并为之生成对应的Class对象。 * a. Bootstrap ClassLoader 根类加载器 * 也被称为引导类加载器,负责Java核心类的加载 * 好比System,String等。在JDK中JRE的lib目录下rt.jar文件中 * b. Extension ClassLoader 扩展类加载器 * 负责JRE的扩展目录中jar包的加载。 * 在JDK中JRE的lib目录下ext目录 * c. System ClassLoader 系统类加载器 * 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。 * 咱们用的是System ClassLoader 系统类加载器
A. 反射定义数组
* a. JAVA反射机制是在运行状态中, 对于任意一个类,都可以知道这个类的全部属性和方法; 对于任意一个对象,都可以调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 * b.反射技术 条件:运行状态 已知:一个类或一个对象(根本是已知.class文件) 结果:获得这个类或对象的全部方法和属性 * 注: 要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.因此先要获取到每个字节码文件对应的Class类型的对象。 *
B. Class类安全
* a. Class类及Class对象的了解 要想解剖一个类,必须先了解Class对象。 阅读API的Class类得知,Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及经过调用类加载器中的 defineClass 方法自动构造的。 * b. 获得Class对象 * 1. 有三个方法 方式一: 经过Object类中的getClass()方法 Person person = new Person(); Class clazz = person.getClass(); 方式二: 经过 类名.class 获取到字节码文件对象(任意数据类型都具有一个class静态属性,看上去要比第一种方式简单)。 Class clazz = Person.class; 方式三: 经过Class类中的方法(将类名做为字符串传递给Class类中的静态方法forName便可)。 Class c3 = Class.forName("Person"); 注:第三种和前两种的区别是: 前两种你必须明确Person类型. 后面是指定这种类型的字符串就行.这种扩展更强.我不须要知道你的类.我只提供字符串,按照配置文件加载就能够了 * 2. 获得Class对象的三个方法代码演示: 代码演示 /* * 获取.class字节码文件对象的方式 * 1:经过Object类中的getObject()方法 * 2: 经过 类名.class 获取到字节码文件对象 * 3: 反射中的方法, * public static Class<?> forName(String className) throws ClassNotFoundException * 返回与带有给定字符串名的类或接口相关联的 Class 对象 */ public class ReflectDemo { public static void main(String[] args) throws ClassNotFoundException { // 1: 经过Object类中的getObject()方法 // Person p1 = new Person(); // Class c1 = p1.getClass(); // System.out.println("c1 = "+ c1); // 2: 经过 类名.class 获取到字节码文件对象 // Class c2 = Person.class; // System.out.println("c2 = "+ c2); // 3: 反射中的方法 Class c3 = Class.forName("cn.itcast_01_Reflect.Person");// 包名.类名 System.out.println("c3 = " + c3); } } Person类 package cn.itcast_01_Reflect; public class Person { //成员变量 public String name; public int age; private String address; //构造方法 public Person() { System.out.println("空参数构造方法"); } public Person(String name) { this.name = name; System.out.println("带有String的构造方法"); } //私有的构造方法 private Person(String name, int age){ this.name = name; this.age = age; System.out.println("带有String,int的构造方法"); } public Person(String name, int age, String address){ this.name = name; this.age = age; this.address = address; System.out.println("带有String, int, String的构造方法"); } //成员方法 //没有返回值没有参数的方法 public void method1(){ System.out.println("没有返回值没有参数的方法"); } //没有返回值,有参数的方法 public void method2(String name){ System.out.println("没有返回值,有参数的方法 name= "+ name); } //有返回值,没有参数 public int method3(){ System.out.println("有返回值,没有参数的方法"); return 123; } //有返回值,有参数的方法 public String method4(String name){ System.out.println("有返回值,有参数的方法"); return "哈哈" + name; } //私有方法 private void method5(){ System.out.println("私有方法"); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]"; } } * 注: Class类型的惟一性 由于一个.class文件在内存里只生成一个Class对象,因此不管那一种方法获得Class对象,获得的都是同一个对象。
C.经过反射获取无参构造方法并使用ide
* a. 获得无参构造方法 public Constructor<?>[] getConstructors() 获取全部的public 修饰的构造方法。 选择无参构造方法,不建议使用。 public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法。 不传参数获得无参构造方法。 * b. 运行无参构造方法 public T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来建立该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 由于是无参构造,因此不传参数。 * c. 经过反射获取无参构造方法并使用的代码演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 经过反射获取class文件中的构造方法,运行构造方法 * 运行构造方法,建立对象 * 获取class文件对象 * 从class文件对象中,获取须要的成员 * * Constructor 描述构造方法对象类 */ public class ReflectDemo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("cn.itcast.demo1.Person"); //使用class文件对象,获取类中的构造方法 // Constructor[] getConstructors() 获取class文件对象中的全部公共的构造方法 /*Constructor[] cons = c.getConstructors(); for(Constructor con : cons){ System.out.println(con); }*/ //获取指定的构造方法,空参数的构造方法 Constructor con = c.getConstructor(); //运行空参数构造方法,Constructor类方法 newInstance()运行获取到的构造方法 Object obj = con.newInstance(); System.out.println(obj.toString()); } }
D. 经过反射获取有参构造方法并使用函数
* a. 获得有参的构造方法 public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法。 传相应的参数类型获得有参构造方法。 * b. 运行无参构造方法 public T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来建立该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 由于是有参构造,因此传相应的参数值。 * c. 经过反射获取有参构造方法并使用的代码演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 经过反射,获取有参数的构造方法并运行 * 方法getConstructor,传递能够构造方法相对应的参数列表便可 */ public class ReflectDemo2 { public static void main(String[] args)throws Exception { Class c = Class.forName("cn.itcast.demo1.Person"); //获取带有,String和int参数的构造方法 //Constructor<T> getConstructor(Class<?>... parameterTypes) //Class<?>... parameterTypes 传递要获取的构造方法的参数列表 Constructor con = c.getConstructor(String.class,int.class); //运行构造方法 // T newInstance(Object... initargs) //Object... initargs 运行构造方法后,传递的实际参数 Object obj = con.newInstance("张三",20); System.out.println(obj); } }
F. 经过反射获取私有构造方法并使用测试
* a. 获得私有的构造方法 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)。 public Constructor<?>[] getDeclaredConstructors() 获取全部的构造方法(包含私有的)。 * b. 运行私有构造方法 public void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。 设置为true,这个方法保证咱们获得的私有构造方法的运行。(取消运行时期的权限检查。) public T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来建立该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 * c. 经过反射获取私有构造方法并使用的代码演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 反射获取私有的构造方法运行 * 不推荐,破坏了程序的封装性,安全性 * 暴力反射 */ public class ReflectDemo4 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); //Constructor[] getDeclaredConstructors()获取全部的构造方法,包括私有的 /*Constructor[] cons = c.getDeclaredConstructors(); for(Constructor con : cons){ System.out.println(con); }*/ //Constructor getDeclaredConstructor(Class...c)获取到指定参数列表的构造方法 Constructor con = c.getDeclaredConstructor(int.class,String.class); //Constructor类,父类AccessibleObject,定义方法setAccessible(boolean b) con.setAccessible(true); Object obj = con.newInstance(18,"lisi"); System.out.println(obj); } } * 注:不推荐,破坏了程序的封装性,安全性。 *
G. 反射获取成员变量并改值this
* a. 获取成员变量 * 获得公共的成员变量 public Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 public Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的全部可访问公共字段。 * 获得全部的成员变量(包括私有的,若是要进行修改私有成员变量,要先进行public void setAccessible(boolean flag) 设置。) public Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 public Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的全部字段。 * b. 修改为员变量(Field)的值 * 修改公共的成员变量 public void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 obj指的是修改的是那个对象的这个成员变量值。 * c. 反射获取成员变量并改值的代码演示 package cn.itcast.demo1; import java.lang.reflect.Field; /* * 反射获取成员变量,并修改值 * Person类中的成员String name */ public class ReflectDemo5 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //获取成员变量 Class类的方法 getFields() class文件中的全部公共的成员变量 //返回值是Field[] Field类描述成员变量对象的类 /*Field[] fields = c.getFields(); for(Field f : fields){ System.out.println(f); }*/ //获取指定的成员变量 String name //Class类的方法 Field getField(传递字符串类型的变量名) 获取指定的成员变量 Field field = c.getField("name"); //Field类的方法 void set(Object obj, Object value) ,修改为员变量的值 //Object obj 必须有对象的支持, Object value 修改后的值 field.set(obj,"王五"); System.out.println(obj); } }
H. 反射获取空参数成员方法并运行spa
* a. 获取空参数成员方法 * 获得公共的成员方法 public Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 * 获得所有的成员方法(包括私有的,若是要使用私有成员方法,要先进行public void setAccessible(boolean flag) 设置。) public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的全部方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 * b. 使用Method方法对象 public Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 obj 指的是调这个方法的对象。 args 指的是调用这个方法所要用到的参数列表。 返回值Object就是方法的返回对象。若是方法没有返回值 ,返回的是null. * c. 反射获取空参数成员方法并运行代码演示 package cn.itcast.demo1; import java.lang.reflect.Method; /* * 反射获取成员方法并运行 * public void eat(){} */ public class ReflectDemo6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //获取class对象中的成员方法 // Method[] getMethods()获取的是class文件中的全部公共成员方法,包括继承的 // Method类是描述成员方法的对象 /*Method[] methods = c.getMethods(); for(Method m : methods){ System.out.println(m); }*/ //获取指定的方法eat运行 // Method getMethod(String methodName,Class...c) // methodName获取的方法名 c 方法的参数列表 Method method = c.getMethod("eat"); //使用Method类中的方法,运行获取到的方法eat //Object invoke(Object obj, Object...o) method.invoke(obj); } }
I. 反射获取有参数成员方法并运行code
* a. 获取有参数成员方法 * 获得公共的成员方法 public Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 * 获得所有的成员方法(包括私有的,若是要使用私有成员方法,要先进行public void setAccessible(boolean flag) 设置。) public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的全部方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 * b. 使用Method方法对象 public Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 obj 指的是调这个方法的对象。 args 指的是调用这个方法所要用到的参数列表。 返回值Object就是方法的返回对象。若是方法没有返回值 ,返回的是null. * c. 反射获取有参数成员方法并运行代码演示 package cn.itcast.demo1; import java.lang.reflect.Method; /* * 反射获取有参数的成员方法并执行 * public void sleep(String,int,double){} */ public class ReflectDemo7 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //调用Class类的方法getMethod获取指定的方法sleep Method method = c.getMethod("sleep", String.class,int.class,double.class); //调用Method类的方法invoke运行sleep方法 method.invoke(obj, "休眠",100,888.99); } }
J. 反射泛型擦除对象
* a. 使用状况 例如:在泛型为String的集合里,添加Integer的数据 ArrayList<String> list = new ArrayList<String>(); list.add(100); * b. 能用泛型擦除的理论 伪泛型:在编译后的.class文件里面是没有泛型的。类型为Object。 用反射的方法绕过编译,获得Class文件对象,直接调用add方法。 * c. 反射泛型擦除的代码演示 package cn.itcast.demo2; import java.lang.reflect.Method; import java.util.ArrayList; /* * 定义集合类,泛型String * 要求向集合中添加Integer类型 * * 反射方式,获取出集合ArrayList类的class文件对象 * 经过class文件对象,调用add方法 * * 对反射调用方法是否理解 */ public class ReflectTest { public static void main(String[] args)throws Exception { ArrayList<String> array = new ArrayList<String>(); array.add("a"); //反射方式,获取出集合ArrayList类的class文件对象 Class c = array.getClass(); //获取ArrayList.class文件中的方法add Method method = c.getMethod("add",Object.class); //使用invoke运行ArrayList方法add method.invoke(array, 150); method.invoke(array, 1500); method.invoke(array, 15000); System.out.println(array); } }
K. 反射经过配置文件来决定运行的步骤
* a. 操做依据 经过配置文件获得类名和要运行的方法名,用反射的操做类名获得对象和调用方法 * b. 实现步骤: * 1. 准备配置文件,键值对 * 2. IO流读取配置文件 Reader * 3. 文件中的键值对存储到集合中 Properties * 集合保存的键值对,就是类名和方法名 * 4. 反射获取指定类的class文件对象 * 5. class文件对象,获取指定的方法 * 6. 运行方法 * c. 代码演示 代码: package cn.itcast.demo3; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; /* * 调用Person方法,调用Student方法,调用Worker方法 * 类不清楚,方法也不清楚 * 经过配置文件实现此功能 * 运行的类名和方法名字,以键值对的形式,写在文本中 * 运行哪一个类,读取配置文件便可 * 实现步骤: * 1. 准备配置文件,键值对 * 2. IO流读取配置文件 Reader * 3. 文件中的键值对存储到集合中 Properties * 集合保存的键值对,就是类名和方法名 * 4. 反射获取指定类的class文件对象 * 5. class文件对象,获取指定的方法 * 6. 运行方法 */ public class Test { public static void main(String[] args) throws Exception{ //IO流读取配置文件 FileReader r = new FileReader("config.properties"); //建立集合对象 Properties pro = new Properties(); //调用集合方法load,传递流对象 pro.load(r); r.close(); //经过键获取值 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //反射获取指定类的class文件对象 Class c = Class.forName(className); Object obj = c.newInstance(); //获取指定的方法名 Method method = c.getMethod(methodName); method.invoke(obj); } } 配置文件: #className=cn.itcast.demo3.Student #methodName=study className=cn.itcast.demo3.Person methodName=eat #className=cn.itcast.demo3.Worker #methodName=job
做业测试
1.ArrayList
这个泛型为Integer的ArrayList中存放一个String类型的对象
2.用反射去建立一个对象,有2种方式,尽可能用代码去体现
4.编写一个类A,增长一个实例方法showString,用于打印一条字符串,
在编写一个类TestA ,做为客户端,用键盘输入一个字符串,该字符串就是类A的全名,使用反射机制建立该类的对象, 并调用该对象中的方法showString
写一个方法,此方法可将obj对象中名为propertyName的属性的值设置为value.
public void setProperty(Object obj, String propertyName, Object value){ }
6.定义一个标准的JavaBean,名叫Person,包含属性name、age。
使用反射的方式建立一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置, 不使用setAge方法直接使用反射方式对age赋值。
7.已知一个类,定义以下:
package com.itheima; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)写一个Properties格式的配置文件,配置类的完整名称。 (2) 写一个程序,读取这个Properties配置文件,得到类的完整名称并加载这个类, (3)用反射 的方式运行run方法。
写一个方法,此方法能够获取obj对象中名为propertyName的属性的值
public Object getProperty(Object obj, String propertyName, Object value){ }
答案:
1.ArrayList<Integer> list = new ArrayList<Integer>(); 这个泛型为Integer的ArrayList中存放一个String类型的对象 package com.itheima.tests; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; /* * 1.ArrayList<Integer> list = new ArrayList<Integer>(); 为这个泛型为Integer的ArrayList中存放一个String类型的对象 */ public class Test01 { public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(10); System.out.println(list); //经过反射获取ArrayList集合的字节码对象 Class clazz = Class.forName("java.util.ArrayList"); //经过反射获取add方法 Method addMethod = clazz.getMethod("add", Object.class); //经过反射调用addMethod方法 addMethod.invoke(list, "reflect is very good!"); System.out.println(list); // HashMap<Integer,Integer> hm = new HashMap<>(); } }
2.用反射去建立一个对象,有2种方式,尽可能用代码去体现
package com.itheima.tests; import java.lang.reflect.Constructor; /** * 2.用反射去建立一个对象,有2种方式,尽可能用代码去体现 * @author JX * */ public class Test02 { public static void main(String[] args) throws Exception { //获取Student类的字节码对象 Class clazz = Class.forName("com.itheima.tests.Student"); //1.利用反射建立一个空的对象 Student student = (Student)clazz.newInstance(); /*//2.获取字段 Field ageField = clazz.getDeclaredField("age"); Field nameField = clazz.getDeclaredField("name"); //取出私有属性 ageField.setAccessible(true); nameField.setAccessible(true); //3.给字段设置值 ageField.set(student, 30); nameField.set(student, "张三"); System.out.println(student);*/ /*Method setAgeMethod = clazz.getMethod("setAge", int.class); Method setNameMethod = clazz.getMethod("setName", String.class); setAgeMethod.invoke(student, 38); setNameMethod.invoke(student, "柳岩"); System.out.println(student);*/ //获取有参构造 Constructor constructor = clazz.getConstructor(int.class,String.class); Student stu = (Student)constructor.newInstance(30,"张亮"); System.out.println(stu); } } class Student { private int age; private String name; public Student() { } public Student(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [age=" + age + ", name=" + name + "]"; } }
编写一个类,增长一个实例方法用于打印一条字符串。
并使用反射手段建立该类的对象, 并调用该对象中的方法。
package com.itheima.tests; import java.lang.reflect.Method; /* * 3. 编写一个类,增长一个实例方法用于打印一条字符串。 并使用反射手段建立该类的对象, 并调用该对象中的方法。 */ public class Test03 { public static void main(String[] args) throws Exception { //获取Demo.java的字节码对象 Class clazz = Class.forName("com.itheima.tests.Demo");//obj.getClass(); Student.class //利用反射建立对象 Demo demo = (Demo)clazz.newInstance(); //利用反射获取print方法 Method printMethod = clazz.getMethod("print",String.class); printMethod.invoke(demo,"Android"); } } class Demo { public Demo() { } public void print(String str ){ System.out.println("Hello "+str); }
}
4.编写一个类A,增长一个实例方法showString,用于打印一条字符串,
在编写一个类TestA ,做为客户端,用键盘输入一个字符串,该字符串就是类A的全名,使用反射机制建立该类的对象,并调用该对象中的方法showString
package com.itheima.tests; import java.lang.reflect.Method; import java.util.Scanner; /* * 4.编写一个类A,增长一个实例方法showString,用于打印一条字符串, 在编写一个类TestA ,做为客户端,用键盘输入一个字符串,该字符串就是类A的全名,使用反射机制建立该类的对象, 并调用该对象中的方法showString */ public class Test04 { public static void main(String[] args) throws Exception{ Scanner sc = new Scanner(System.in); System.out.println("请输入一个类的全类名,用.隔开:"); String className = sc.nextLine(); Class clazz = Class.forName(className);//obj.getClass(); Student.class //利用反射建立对象 A a = (A)clazz.newInstance(); //利用反射获取print方法 Method printMethod = clazz.getMethod("showString"); printMethod.invoke(a); } } class A { public void showString() { System.out.println(" e m t f 明天必定经过!"); } }
写一个方法,此方法可将obj对象中名为propertyName的属性的值设置为value.
public void setProperty(Object obj, String propertyName, Object value){ } package com.itheima.tests; import java.lang.reflect.Field; /** * 5. 写一个方法,此方法可将obj对象中名为propertyName的属性的值设置为value. public void setProperty(Object obj, String propertyName, Object value){ } * @author JX * */ public class Test05 { public static void main(String[] args) throws Exception { Student student = new Student(30,"张三"); setProperty(student, "age", 25); System.out.println(student); Object obj = getProperty(student, "name"); System.out.println(obj); } //给对象obj的名字为propertyName的属性设置为value public static void setProperty(Object obj, String propertyName, Object value) throws Exception{ //1.获取obj的字节码对象 Class clazz = obj.getClass(); //2.获取propertyName属性对应的Field对象 Field propertyNameField = clazz.getDeclaredField(propertyName); //3.设置成可访问的 propertyNameField.setAccessible(true); //4.调用set方法给对象赋值 propertyNameField.set(obj, value); } //给对象obj的名字为propertyName的属性设置为value public static Object getProperty(Object obj, String propertyName) throws Exception{ //1.获取obj的字节码对象 Class clazz = obj.getClass(); //2.获取propertyName属性对应的Field对象 Field propertyNameField = clazz.getDeclaredField(propertyName); //3.设置成可访问的 propertyNameField.setAccessible(true); //4.调用get方法获取该对象对应属性的值 return propertyNameField.get(obj); } }
6.定义一个标准的JavaBean,名叫Person,包含属性name、age。
使用反射的方式建立一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置, 不使用setAge方法直接使用反射方式对age赋值。 package com.itheima.tests; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /* * 6.定义一个标准的JavaBean,名叫Person,包含属性name、age。 使用反射的方式建立一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置, 不使用setAge方法直接使用反射方式对age赋值。 */ public class Test06 { public static void main(String[] args) throws Exception, SecurityException { //1.获取Person类的字节码对象 Class clazz = Person.class; //2.利用反射获取有参构造方法 Constructor constructor = clazz.getConstructor(int.class,String.class); //3.调用构造方法,给属性初始化 Person person = (Person)constructor.newInstance(30,"灭绝师太"); System.out.println(person); //4.使用反射方式调用setName方法对名称进行设置 Method setNameMethod = clazz.getMethod("setName", String.class); setNameMethod.invoke(person, "张三丰"); //5.不使用setAge方法直接使用反射方式对age赋值。 Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(person, 50); System.out.println(person); } } class Person { private int age; private String name; public Person() { } public Person(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } }
7.已知一个类,定义以下:
package com.itheima; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)写一个Properties格式的配置文件,配置类的完整名称。 (2) 写一个程序,读取这个Properties配置文件,得到类的完整名称并加载这个类, (3)用反射 的方式运行run方法。 package com.itheima.tests; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; /** * 7.已知一个类,定义以下: package com.itheima.tests; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)写一个Properties格式的配置文件,配置类的完整名称。 (2) 写一个程序,读取这个Properties配置文件,得到类的完整名称并加载这个类, (3)用反射 的方式运行run方法。 * @author JX * */ public class Test07 { public static void main(String[] args) throws Exception { /*Properties props = new Properties(); props.load(new FileInputStream("src/config.properties")); String className = (String) props.get("className");*/ //定义字符缓冲输入流 BufferedReader br = new BufferedReader(new FileReader("src/config.properties")); String line = br.readLine(); String className = line.split("=")[1]; // System.out.println(className); Class clazz = Class.forName(className); //利用反射建立一个对象 Object obj = clazz.newInstance(); //利用反射获取run方法 Method runMethod = clazz.getMethod("run"); //利用反射调用run方法 runMethod.invoke(obj); } }
写一个方法,此方法能够获取obj对象中名为propertyName的属性的值
public static Object getProperty(Object obj, String propertyName, Object value){ } package com.itheima.tests2; import java.lang.reflect.Field; public class Test08 { public static void main(String[] args) throws Exception { Person person = new Person(20,"张三"); String name = (String)getProperty(person, "name"); System.out.println(name); } public static Object getProperty(Object obj, String propertyName) throws Exception{ //获取obj对象的字节码文件对象 Class clazz = obj.getClass(); //获取propertyName属性所对应的字段 Field field = clazz.getDeclaredField(propertyName); //去掉私有属性 field.setAccessible(true); return field.get(obj); } }