简述
反射是在运行时而非编译时动态获取类型的信息(接口信息,成员信息,方法信息,构造方法信息等)然后依据这些动态获取到的信息创建对象,访问修改成员,调用方法等。反射可以在运行时判断任意一个对象所属的类,任意一个类的成员变量和方法,调用任何一个类的方法,构造任意一个类的对象;生成动态代理。
可通过Class.forName(“类名”)方法可以访问返回一个指定类名的类对象,因为在java里面任何一个class都要装载在虚拟机上才能运行,所以这方法的作用是装载类而用。
当我们获取到Class对象后,通过Field字段,Method字段,Constructor字段,和相应的方法分别可以得到类中的属性,普通方法,构造方法。
获取类中属性和方法
1.创建一个类 Student
package Project;
public class Student {
private String name;
public String sex;
int age;
protected int id;
public Student() { }
public Student(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public void show() { }
public void init(String name,int id){}
}
2.创建一个测试类用于打印Student中的基本信息
package Project;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Text {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方法
//Class stu=Project.Student.class;
//第二种方法(需要先创建对象 然后通过对象获得Class)
//Student student=new Student();
//Class stu=student.getClass();
//第三种方法(推荐使用)
Class stu=Class.forName("Project.Student");//得到类的Class对象
StringBuffer sb=new StringBuffer();//用于保存需要反射类中的信息
// 得到类的修饰符 类名
sb.append(Modifier.toString(stu.getModifiers())+" class "+stu.getName()+" {\n");
Field field[]=stu.getDeclaredFields();//得到所有的属性
for(Field fd:field){ //属性的访问修饰符 返回值类型 属性名
sb.append("\t"+Modifier.toString(fd.getModifiers())+" "+fd.getType().getName()+" "+fd.getName()+" \n");
}
//得到普通方法
Method[] modifier=stu.getDeclaredMethods();//得到所有的普通方法
for(Method md:modifier){// 方法访问修饰符 返回值类型 方法名
sb.append("\t"+Modifier.toString(md.getModifiers())+" "+md.getReturnType().getName()+" "+md.getName()+" (");
// 得到方法的所有返回值
Class returns[]=md.getParameterTypes();//因为方法的返回值可能不止一个(也可能没有)所以用数组存放所有返回值
for(Class rt:returns){//如果方法的返回值不是最后一个 就用“,”隔开
if(rt!=returns[returns.length-1]) sb.append(rt.getName() +",");
else sb.append(rt.getName());
}
sb.append("){\n\t}\n");
}
//得到构造函数
Constructor constructor[]=stu.getDeclaredConstructors();
for(Constructor con:constructor){//构造方法的访问修饰符 构造方法名就是类名
sb.append("\t"+Modifier.toString(con.getModifiers())+" "+stu.getName()+"(");
Class reterns[]=con.getParameterTypes();//得到所有返回值
for(Class rt:reterns){
if(rt!=reterns[reterns.length-1]) sb.append(rt.getName()+",");
else sb.append(rt.getName());
}
sb.append("){\t}\n");
}
sb.append("\n}");
System.out.println(sb);
}
}
3.运行结果:
类中的基本信息已经可以获取到了,至于方法的参数列表就不重要了,我们只需知道它的参数类型就可以调用。
总结
我们可以运行期间通过Method得到类中的方法,然后调用对应的方法。也可以通过Constructor得到对应的构造方法,得到该对象。反射在Java中的用处还是挺多的,在JavaSE中可能不怎么会出现。在后面JavaEE的框架中用处很多。或许有人会这么说:无反射,无框架。其实也不无道理。