这个是我在学习java反射技术时的一个小Demo,理解了它你说你不会java反射,人家都不相信。
下面的这个类是一个JavaBean,我们要做的事情修改JaveBean中所有的String类型的成员变量的值,将’b’修改为’a’:
package com.mari.reflect;
/**
* @author sync
*
*/
public class ReflectPoint {
public String str1 = "ball";
private String str2 = "basketball";
private String str3 = "adflash";
private int x;
private int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
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;
}
@Override
public String toString() {
return "ReflectPoint [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3 + "]";
}
}
下面这个是测试类:
package com.mari.reflect;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws Exception {
//测试修改String类型成员变量的值
ReflectPoint reflectPoint = new ReflectPoint(3, 5);
System.out.println(reflectPoint);
changeStringValue(reflectPoint);
System.out.println(reflectPoint);
System.out.println("=====================================");
//调用main函数时,需要将数组转化成为Object对象
Method methodMain = TestArgument.class.getMethod("main", String[].class);
methodMain.invoke(null, (Object) new String[]{"123", "321", "abc"});
System.out.println("=====================================");
//测试class.isArray, Array.get
String[] a1 = new String[]{"a","b","c","d"};
int[] a2 = new int[]{1,2,3,4};
String s1 = "aaaaaaaaaa";
printObject(a1);
printObject(a2);
printObject(s1);
}
//判断传递过来的参数是否是Array类型,这里也说明了在java中同一个类型的字节码文件只会在内存中加载一次.
//通过查看源码也可以发现在每次加载时会先判断缓存的CacheClass是否存在.存在就返回CacheClass.不存在才
//会去加载Class
private static void printObject(Object obj){
Class<?> cls = obj.getClass();
if (cls.isArray()) {
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
System.out.println(Array.get(obj, i));
}
} else {
System.out.println(obj);
}
}
//使用反射技术动态修改String类型的成员变量的值.
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.getType() == String.class) {
field.setAccessible(true);
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
}
//测试main函数的类,反射调用mian函数时参数不能直接传入数组类型,需要转换成Object类型才能正常调用.
//这个原因可能是和java的自动装箱拆箱或者可变参数类型有关系吧
//具体的我也不清楚了,有哪位读者清楚的话,欢迎留言.
class TestArgument {
public static void main(String[] args) {
for (String string : args) {
System.out.println(string);
}
}
}
下面是测试类的输出结果:
ReflectPoint [str1=ball, str2=basketball, str3=adflash]
ReflectPoint [str1=aall, str2=aasketaall, str3=adflash]
=====================================
123
321
abc
=====================================
a
b
c
d
1
2
3
4
aaaaaaaaaa