上一篇介绍了Java反射之构造方法反射。这次我们在说一说如何反射类中的成员变量并用作一个简单案例。
[一]Field类
Filed类代表字段,包含字段拥有的所有属性,比如修饰符,变量类型,值等等,Filed类中有获得这些属性的方法。
和Constructor类一样都继承了java.lang.reflect.AccessibleObject类,该类中有方法来判断和设置私有属性能否访问。
下面举个演示如何修改、获得某个类中的变量:
Point类:
public class Point { public int x; private int y; public static int z = 10; public Point(int x, int y) { super(); this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } }
测试方法:
public static void main(String[] args) throws Exception { Point p = new Point(3,4); Class cls = p.getClass(); //1、获得Point类中所有的成员变量 Field[] fields = cls.getFields(); //打印 for(Field field : fields){ //get(p);获得对象p的所有成员变量 System.out.println(field.get(p)); } //2、获得Point类中的指定x,y,z变量 Field fieldX = cls.getField("x"); Field fieldY = cls.getField("y"); Field fieldZ = cls.getField("z"); //分别对应对象p System.out.println("x:"+fieldX.get(p)+" y:"+fieldY.get(p)+" z:"+fieldZ.get(null)); }
结果:
3 10 Exception in thread "main" java.lang.NoSuchFieldException: y at java.lang.Class.getField(Class.java:1584) at club.leyvan.muzile.ConstructDemo.main(ConstructDemo.java:20)
Class类中的getFields():获得该类的所有字段作为Field类的对象。
Class类中的getFields(String name):获得该类中和参数同名的字段。
Filed类中的get(p):绑定这个字段是哪一个对象身上的。例子中传了p,代表该方法将field对应对象的成员字段绑定给特定对象p及为对象p中对象名称字段的值。
静态变量属于类所以不需要绑定特定对象,传入null即可获得静态字段值。
第一部分的代码除了私有变量都打印出来了,而第二部分报了错,没有y这个私有变量,暂时我们可以看出私有变量是无法读取的。我们现在把代码修改以下,让它可以获得私有变量的值。
修改后代码如下:
public static void main(String[] args) throws Exception { Point p = new Point(3,4); Class cls = p.getClass(); //1、获得Point类中所有的成员变量 Field[] fields = cls.getFields(); //打印 for(Field field : fields){ //get(p);获得对象p的所有成员变量 System.out.println(field.get(p)); } //2、获得Point类中的指定x,y,z变量 Field fieldX = cls.getField("x"); //修改部分↓↓ Field fieldY = cls.getDeclaredField("y"); fieldY.setAccessible(true); //修改部分↑↑ Field fieldZ = cls.getField("z"); //分别对应对象p System.out.println("x:"+fieldX.get(p)+" y:"+fieldY.get(p)+" z:"+fieldZ.get(null)); }
结果:
3 10 x:3 y:4 z:10
Class类中getDeclaredField(String name):获得私有变量
Field类继承的类java.lang.reflect.AccessibleObject中有setAccessible(boolean b):设置是否可以访问私有成员。
上面的方法又叫暴力反射,可以暴力获取私有成员。
[二]案例:利用反射的方式将一个类中的String类型的变量中所有的"b"修改为"a"
Bean类:
package club.leyvan.muzile; public class Bean { public int i1 = 10; public String str1 = "basketball"; private String str2 = "breakfast"; private static String str3 = "bbc"; @Override public String toString() { return "Bean [i1=" + i1 + ", str1=" + str1 + ", str2=" + str2 + "]"; } public static String getStr3(){ return "str3: "+str3; } }
测试方法:
public static void main(String[] args) throws Exception { //获得class Class cls = Class.forName("club.leyvan.muzile.Bean"); //创建一个对象 默认调用无参构造方法 Bean obj = (Bean)cls.newInstance(); //获得所有字段 Field[] fields = cls.getDeclaredFields(); //扫描所有字段 for(Field field : fields){ //class对象只有一份,所以使用==更好 if(field.getType() == String.class){ //判断是否是 if(!field.isAccessible()){ field.setAccessible(true); } //判断是否是静态字段 //getModifiers()获得所有的修饰符 //boolean isStatic = Modifier.isStatic(field.getModifiers()); String oldValue = (String)field.get(obj); String newValue = oldValue.replace('b', 'a'); field.set(obj, newValue); } } System.out.println(obj+Bean.getStr3()); }
结果:
Bean [i1=10, str1=aasketaall, str2=areakfast]str3: aac
其中field.getModifiers():获得所有的修饰符
Modifier.isStatic():通过获得修饰符判断是否是static
field.set(obj,value):修改绑定对象的值
下一篇我们说Java反射之成员方法的反射
来源:https://www.cnblogs.com/leyvan/p/12461699.html