反射就是把java类中各种成分映射成相应的java类。例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的java类。表示java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应的类德实例对象来表示,它们是Field、Method、Contructor、Package等等。
个人观点:反射就是通过操作类的字节码得到相应的对象的各种成分,然后进行相应的操作。
实例代码:
首先先定义一个共反射类操作的类:
public class Bean {
private int age;
public String name;
public String str1="ball";
public String str2="baskball";
public String str3="football";
public Bean(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Bean other = (Bean) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return str1+" : "+str2+" : "+str3;
}
}
上面其实就是一个简单的类,下面就让我们用反射来操作上面的类:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.itcast.testBean.Bean;
public class Test2 {
/**
* @param args
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Bean b = new Bean(20, "sps");
Field field=b.getClass().getField("name");//注意:此时只是得到了class文件中的field,并没有赋予具体的值
System.out.print(field.get(b));//用field的get传入具体的对像,才能得到具体的对象的field对应的值注意:得不到private的值
// Field field2=b.getClass().getField("age");//注意:age 的field是private的(报错NoSuchFieldException)
// System.out.print(field2.get(b));//用field的get传入具体的对像,才能得到具体的对象的field对应的值注意:得不到private的值
Field field2=b.getClass().getDeclaredField("age");//此方法得到所有的声明成员变量
// System.out.println(field2.get(b));//此方法报错说是此变量是私有的。
field2.setAccessible(true);//暴力得到私有变量
System.out.println(field2.get(b));
setNew(b);
System.out.println(b);
Method method=String.class.getMethod("charAt", int.class);//得到string的charAt方法
System.out.println(method.invoke(new String("abc"), new Object[]{2}));;//动态调用charAt方法(需要调用的对象及其传入的参数)
//invoke 方法如果是静态的时,第一个参数可以传入null例如invoke(null,new object[]{2})
}
/**
* 动态改变原来类中的已经定义的成员对象的赋值,并赋予新的值
* @param obj
* @throws Exception
*/
public static void setNew(Object obj) throws Exception{
Field[] fields=obj.getClass().getFields();
for(Field field:fields){
if(field.getType()==String.class){
String oldStr=(String)field.get(obj);
String newStr=oldStr.replace('b', 'a');
field.set(obj, newStr);
}
}
}
}
上面分别用反射来操作Bean类中的数据,并进行输出测试。最后那个setNew方法利用反射将一个对象中所有的的String变量中b的值替换为a,并重新赋予相应的变量。