反射获取成员变量并使用1
成员变量也称为字段
在Class类里面有一个方法,可以获取学生类的成员变量并使用 1、字段[] getFields() 返回一个包含字段对象的数组,字段对象反映此类对象所表示的类或接口的所有可访问公共字段。只拿公共的成员变量 2、字段[] getDeclaredFields() 返回字段对象的数组,字段对象反映由此类对象表示的类或接口声明的所有字段。拿所有的成员变量 3、字段 getField(String name) 返回字段对象,该对象反映此类对象表示的类或接口的指定公共成员字段。只拿某个公共的成员变量 4、字段 getDeclaredField(String name) 返回字段对象,该对象反映此类对象表示的类或接口的指定声明字段。只拿某个成员变量
我们来学习一下Field类。该类在java.lang.reflect包下。该类被final修饰,即该类是具体类 该类的作用是字段提供有关类或接口的单个字段的信息和动态访问
该类有一个方法:void set(Object obj, Object value) 将指定对象参数上此字段对象表示的字段设置为指定的新值,简单理解就是用于给obj对象的成员变量赋值为value
反射获取成员变量并使用1的练习
xxxxxxxxxxpackage ch27;
public class a_8_1Student {
//成员变量:私有、默认、公共 private String name; int age; public String address;
//公共构造方法,这里的这个也叫无参构造方法 public a_8_1Student() { } //私有构造方法 private a_8_1Student(String name) { this.name = name; } //默认构造方法 a_8_1Student(String name, int age) { this.name = name; this.age = age; } //公共构造方法 public a_8_1Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
//私有成员方法 private void function(){ System.out.println("function"); } //4个公共成员方法 public void method1(){ System.out.println("method"); } public void method2(String s){ System.out.println("method:"+s); } public String method3(String s,int i){ return s + "," + i; }
//重写的toString方法也是公共成员方法 public String toString() { return "a_4_1Student{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }x
package ch27;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;
public class a_8_2测试 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取学生类的Class对象 Class<?> c = Class.forName("ch27.a_8_1Student");
//--------------------------------------------------------------------------------------------------------
//获取学生类的成员变量并使用 Field[] fields = c.getFields(); //遍历拿到的字段数组,即遍历拿到的成员变量 for(Field field : fields){ System.out.println(field); //上面那行输出public java.lang.String ch27.a_8_1Student.address,即只输出公共的成员变量 } System.out.println("---------上面拿的是公共的成员变量------------"); System.out.println();
//--------------------------------------------------------------------------------------------------------
//如何也拿到学生类里面的默认和私有成员变量呢 Field[] fields2 = c.getDeclaredFields(); for(Field field : fields2){ System.out.println(field);//输出全部的成员变量,包括公共、默认、私有的成员变量 } System.out.println("---------上面拿的是全部的成员变量-------------"); System.out.println();
//--------------------------------------------------------------------------------------------------------
//如何只拿学生类里面的指定某个公共成员变量呢,如下 Field addressField = c.getField("address");//只拿学生类里面的address公共成员变量 //上面那行拿到的是address成员变量对应的成员变量方法的对象,如何使用这个对象,如下
//获取公共无参构造方法的对象 Constructor<?> con = c.getConstructor();//由于获取的是无参构造方法的对象,所以右边是没有参数的 Object obj = con.newInstance();//newInstance获取对象,同理右边无参
//Field类的作用是字段提供有关类或接口的单个字段的信息和动态访问 //该类有一个方法:void set(Object obj, Object value) 将指定对象参数上此字段对象表示的字段设置为指定的新值 addressField.set(obj,"厦门");//通过38行的成员对象来调用set方法 //上面那行的set方法是给obj的成员变量addressField赋值为厦门,其实就是给38行的address成员变量赋值为厦门 System.out.println(obj); System.out.println("---------给学生类的某个成员变量赋值-反射-------------"); System.out.println();
//--------------------------------------------------------------------------------------------------------
//之前的多态的方式 a_8_1Student s = new a_8_1Student(); s.address = "厦门2"; System.out.println(s); System.out.println("---------给学生类的某个成员变量赋值-多态-------------"); System.out.println();
}}
反射获取成员变量并使用2
练习:通过反射实现如下操作 1、Student s = new Student(); 2、s.name = "张三"; 3、s.age = 18; 4、s.address = "厦门"; 5、System.out.println(s);
反射获取成员变量并使用2的练习
xxxxxxxxxxpackage ch27;
public class a_9_1Student {
//成员变量:私有、默认、公共 private String name; int age; public String address;
//公共构造方法,这里的这个也叫无参构造方法 public a_9_1Student() { } //私有构造方法 private a_9_1Student(String name) { this.name = name; } //默认构造方法 a_9_1Student(String name, int age) { this.name = name; this.age = age; } //公共构造方法 public a_9_1Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
//私有成员方法 private void function(){ System.out.println("function"); } //4个公共成员方法 public void method1(){ System.out.println("method"); } public void method2(String s){ System.out.println("method:"+s); } public String method3(String s,int i){ return s + "," + i; }
//重写的toString方法也是公共成员方法 public String toString() { return "a_4_1Student{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }xxxxxxxxxxpackage ch27;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;
public class a_9_2测试 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//获取学生类的Class对象 Class<?> c = Class.forName("ch27.a_9_1Student");
//------------------------------------------------------------------------------------------------------
//【1、Student s = new Student();】
//通过无参构造方法来创建学生类的对象 Constructor<?> con = c.getConstructor(); //生成对象obj Object obj = con.newInstance(); System.out.println(obj); //上面的代码还没有给学生类的成员变量赋值 //输出a_4_1Student{name='null', age=0, address='null'}
System.out.println("--------上面的是通过反射来创建学生类的对象-还未赋值---------"); System.out.println(); //------------------------------------------------------------------------------------------------------
//【2、s.name = "张三";】
/*//c调用getfield得到某个成员变量的对象 Field nameField = c.getField("name"); //通过成员变量对象调用set方法给obj对象赋值为张三 nameField.set(obj,"张三"); //上面那行是给obj的成员变量nameField的31行的name赋值为张三 System.out.println(obj); //上面那行会报错,原因:学生类的name成员变量被private修饰,上面31行的getField无法给私有成员变量赋值。上面报错先注释,需要自行解开*/
//解决如下 Field nameField = c.getDeclaredField("name"); //暴力反射 nameField.setAccessible(true);//暴力反射,即当setAccessible方法的参数为true时,取消访问检查 nameField.set(obj,"张三");//在这行上面加一个暴力反射,即setAccessible方法 System.out.println(obj); //输出a_4_1Student{name='张三', age=0, address='null'}
System.out.println("----------上面的是给学生类的私有成员变量name赋值-----------"); System.out.println(); //------------------------------------------------------------------------------------------------------
//【3、s.age = 18;】 Field ageField = c.getDeclaredField("age"); ageField.setAccessible(true);//暴力反射 ageField.set(obj,18); //上面那行是给obj对象的ageField的49行的age赋值为18 System.out.println(obj);
System.out.println("-----------上面的是给学生类的默认成员变量age赋值------------"); System.out.println(); //------------------------------------------------------------------------------------------------------
//【4、s.address = "厦门";】 //当不确定address是不是私有的成员变量时,就使用getDeclaredField方法,如下。(即使我们知道address是公共成员变量,而不是私有,也可这样做) Field addressField = c.getDeclaredField("address"); addressField.setAccessible(true);//暴力反射
addressField.set(obj,"厦门"); //上面那行是给obj对象的addressField的68行的address赋值为"厦门" System.out.println(obj);
System.out.println("---------上面的是给学生类的公共成员变量address赋值----------"); System.out.println();
}}