相信很多Java新手都和我一样对Java中反射机制不是很了解,所以特别花时间去学习了一下反射机制。下面是我自己的一些学习的总结,写得不太到位的希望大家各位大牛指出,大家一起学习。
一、什么是反射?
Java反射机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
简单点说,就是通过一个类的类名或者对象,就能知道这个这个类里面的所有的属性和方法,对于任意一个对象,都能调用这个对象内的任意方法。
二、作用与优点
反射机制最大的就是增强程序的灵活性,但是使用不当的话,会影响程序的效率。
三、反射机制提供的一些功能
在看功能之前,我们先写一个Student类,里面分别有name(姓名),stu_num(学号)两个字段,有一个无参和带两个参数的构造方法,两个字段都写了get和set方法。
Student类代码:
public class Student {
//学生的姓名
String name;
//学生的学号
private int stu_num;
/**
* 带参数的构造方法
* @param name
* @param stu_num
*/
public Student(String name, int stu_num) {
super();
this.name = name;
this.stu_num = stu_num;
}
/**
* 无参构造方法
*/
public Student(){
super();
}
//get和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getStu_num() {
return stu_num;
}
public void setStu_num(int stu_num) {
this.stu_num = stu_num;
}
}
1、获取类的Class对象
//第一种,直接通过Student类来获得Class对象
Class cls1=Student.class;
System.out.println(cls1);
//第二种,通过实例来获得Student类的字节码
//每个类型都有getClass()方法
Student stu=new Student();
Class cls2=stu.getClass();
System.out.println(cls2);
//第三种,调用Class类的静态方法forName
//该方法会抛出异常,但是使用得比较多一点
try {
Class cls3=Class.forName("com.yds.reflect.Student");
System.out.println(cls3);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
运行代码可以看到控制台输出三个一样的值,都是class com.yds.reflect.Student。另外我们需要知道Class就是Java抽象类,它抽象出了java的共性,如类名,构造方法等,我们每创建一个类,如Student类,实际上就是实例化了一个Class的实例,保存Student的名字、变量、方法等信息。在内存中就是保存了Student类的字节码。
2、获取类的Fields
知道类里面有哪些域的情况下可以通过以下方法去访问和获得域:
<span style="font-size:14px;"> <span style="font-size:14px;">//创建一个学生对象</span>
Student stu_a=new Student("小王",20131000);
//通过对象获得class对象
Class cls4=stu_a.getClass();
//fieldName不代表具体的值,只代表Student类里面name这个变量
//所以需要传入一个Student实例才能获取到其对应值
Field fieldName=cls4.getField("name");
System.out.println(fieldName);
System.out.println(fieldName.get(stu_a));
//stu为私有的,用getDeclaredField来获取Student类的私有变量
//并且设置该私有变量可以强制访问
Field fieldNum=cls4.getDeclaredField("stu_num");
fieldNum.setAccessible(true);
System.out.println(fieldNum);
System.out.println(fieldNum.get(stu_a));</span>
在不知道类里面有哪些域的时候,可以通过getFields()和getDeclaredFields()来分别获得类里面的域
//在并不知道一个类里面有哪些域的时候可以用用数组把他们全部取出来
Field[] fields=cls4.getFields();
for(Field f:fields){
System.out.println(f.getName());
}
//私有域通过getDeclaredFields()来获得,然后遍历整个数组
Field[] fields2=cls4.getDeclaredFields();
for(Field f:fields2){
System.out.println(f.getName());
}<strong>
</strong>
3、获得类的Methdod
方法的获取和域的获取非常类似,只是有的方法获取和调用需要传入参数,获取方法时传入的参数为调用时传入参数的类型
//获得setName()这个方法,传入的参数为String类型的
//cls2为没有传参数构造的Class对象
//如果是没有参数的话则传入Null
Method method1=cls2.getMethod("setName", String.class);
method1.invoke(stu, "张三丰");
Method method2=cls2.getMethod("getName", null);
//invoke返回类型为Object
String name=(String)method2.invoke(stu, null);
System.out.println(name);
4、获得类的Constructor
//获得无参构造方法
Constructor constructor=cls1.getConstructor();
System.out.println(constructor);
//获得所有的构造方法
Constructor[] csts=cls1.getConstructors();
for(Constructor c:csts){
System.out.println(c);
}
5、获得类的实例
//使用newInstance构造实例
Student stu_instance=(Student) cls1.newInstance();
只是简单学习了一些反射机制,各位有兴趣的可以深入去研究一下,还是挺有意思的。还有就是一定要自己写代码,自己运行过的东西感觉才能记得住。