当我大学第一次接触到反射的时候,我就在想下面三个问题。
什么是反射?
反射怎么用?
什么时候用它?
当我弄清楚这三个问题的时候,我突然发现,反射实在太强大,它简直无处不在不管是多大的项目,不论是任何Java框架,反射都在里面充当着必不可少的角色。
回到最初的三个问题。
第一、什么反射?
其实简单的说反射就是动态的获取或修改类的信息(包括类)。我相信每个Java coder都知道java分编译时和运行时,通常情况下coder都是静态的定义或获取类的信息,这种情况下定义的类都会在编译时被编译器编译。但是反射是在运行时获取或加载类的信息,它可以让你动态的修改一些已经定义好的类信息。
第二、反射怎么用?
反射怎么用,就和平常写代码一样,获取一个类的实例,初始化类的信息,然后调用类的方法,将一些参数传入要调用的方法内。对,没错,就是这么简单,只不过反射换了一种方式来做这些事情。当地是什么方式呢,让我们来看个demo一探究竟吧。
首先写了一个bean.
public class Student implements Serializable {
private Integer id;
private String name;
private int age;
private String depart;
private Date birthday;
private String gender;
public Student() {
// TODO Auto-generated constructor stub
}
public Student(String name,int age,String depart){
this.name= name;
this.age = age;
this.depart = depart;
}
/*省略getter setter method*/
public String toString(){
return "name:"+this.name+
"\n age:"+this.age+"\n depart:"+this.depart;
}
public void writeSome(String name){
System.out.println("name:"+name);
}
public void writeSome(String name,String depart){
System.out.println("name:"+name+"\t depart:"+depart);
}
}
用下面的代码动态获取类信息。
Class<?> clazz = Class.forName("com.hal.entity.Student");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("field name:"+field.getName());
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("method name:"+method.getName());
}
这是输出信息:
*field name:id
field name:name
field name:age
field name:depart
field name:birthday
field name:gender
method name:toString
method name:getName
method name:getId
method name:setName
method name:writeSome
method name:writeSome
method name:setId
method name:getAge
method name:setAge
method name:getDepart
method name:setDepart
method name:getBirthday
method name:setBirthday
method name:getGender
method name:setGender*
当然还有很多其他的方法,具体的请看API.
反射还能实现代理或者动态加载方法。
Object object = clazz.newInstance();
System.out.println(object.getClass().getName());
Method method = clazz.getDeclaredMethod("writeSome",String.class);
method.invoke(object,"steven");
Object object = clazz.newInstance()就是初始化对象了,相当于new一个对象。
getDeclaredMethod(String paramString, Class<?> paramArrayOfClass)
第一个参数是方法名,第二个参数是一个可变长参数,是指方法的参数类型。
运行该段代码就会加载bean中的这个方法:
public void writeSome(String name){
System.out.println(“name:”+name);
}
第三、什么时候用反射
学了东西肯定要使用出来才能产生价值,但是也不能乱用,不然反而会适得其反。其实大家无时无刻都在用着反射,反射也总是在帮coder提高效率。
- JDK的动态代理
- cglib基于类的代理
- Spring 的AOP
- 依赖注入
- 属性拷贝
等等。底层大部分都是用反射来实现了。
记住,当需要动态获取或修改一些类信息时,就可以使用反射来完成。
最后附上一段动态改变数组长度的demo
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = (int[])intitalArray();
print(arr);
int[] newArr =(int[]) changeArrayLength(arr, 10);
print(newArr);
}
private static Object intitalArray(){
int[] arr = {1,2,3,4,5};
return arr;
}
private static Object changeArrayLength(Object object,int len){
Class<?> clazz = object.getClass();
System.out.println(clazz);
Object newArr = Array.newInstance(clazz, len);
int newlen = Array.getLength(object);
System.arraycopy(object, 0, newArr,5, newlen);
return newArr;
}
private static void print(Object object){
Class<?> clazz = object.getClass();
if (!clazz.isArray()) {
return;
}
int len =Array.getLength(object) ;
System.out.println("array length: "+len);
for (int i = 0; i < len; i++) {
System.out.println(Array.get(object, i));
}
}
以上纯属个人理解,如有任何问题,还望指正。
谢谢。