反射
反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序。大量的框架中都用到了反射技术,我所接触过的反射技术一般都与接口结合使用,具体怎么实现,下面详细讲解。
有关于本文提到的类库的方法信息,请详见java api 文档;
1 java.lang.Class 类
java运行时系统始终为所有对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。
我们可以根据一个实例找到他所属的对应的类信息。
package reflect;
public class Employee {
public static void main(String[] args) {
Employee e = new Employee();
Class cl = e.getClass();
System.out.println(cl.getName());
}
}
输出结果:
reflect.Employee
我们可以看到,输出结果为该实例 e 所对应的类信息的全路径名称(包括包名)。
利用反射实现利用类的全路径名称得到一个该类的实例。
package reflect;
public class Employee {
public static int count = 0;
public Employee() {
count++;
}
public static int getCount() {
return count;
}
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
Employee e = new Employee();
System.out.println(e.getCount());
Employee e1 = (Employee) Class.forName("reflect.Employee").newInstance();
System.out.println(e1.getCount());
}
}
输出结果:
1
2
通过上述的例子,我们可以看出,我们建立了两个实例,一个是通过正常的方式,一个是通过反射的方式,而在实际开发中,在反射的强制类型转化时,我们一般将其转化为接口类型,然后使得Employee实现该接口,根据java的动态加载特点,就可以大大的提高代码的灵活性。newInstance()方法其实就是Employee类的无参构造方法。
2 java.lang.reflect.Field 类
java是一种面向对象的语言,一切皆为对象,通过Class信息,我们可以得到这个类的所有字段信息。
package reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Employee {
public static int count = 0;
public String name = "tjy";
public int age = 26;
private double sar = 20.00;
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
Class cl = Class.forName("reflect.Employee");
//获得类的所有字段
Field[] fields = cl.getDeclaredFields();
for(Field f : fields){
//得到字段类型
Class type = f.getType();
//得到字段名字
String name = f.getName();
//获取字段的域
String modifiers = Modifier.toString(f.getModifiers());
if(modifiers.length() >0){
System.out.print(modifiers + " ");
}
System.out.println(type.getName()+": "+name+";");
}
}
}
输出结果:
public static int: count;
public java.lang.String: name;
public int: age;
private double: sar;
3 java.lang.reflect.Method 类
package reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Employee {
public static String name = "tjy";
public void sayHello(){
System.out.println("Hello");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
Class cl = Class.forName("reflect.Employee");
//获得类的所有方法
Method[] methods = cl.getDeclaredMethods();
for(Method method:methods){
//获取方法返回值类型
Class type = method.getReturnType();
//获取方法名称
String name = method.getName();
//获取方法域
String modifiers = Modifier.toString(method.getModifiers());
if(modifiers.length() > 0){
System.out.print(modifiers+" ");
}
System.out.println(type.getName()+": "+name+";");
}
}
}
输出结果:
public void: sayHello;
public java.lang.String: getName;
public void: setName;
public static void: main;
此示例展示利用类得到该类的方法信息。下面介绍怎么通过得到的方法信息来调用方法。
package reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Employee {
public static String name = "tjy";
public void sayHello(){
System.out.println("Hello");
}
public static void sayName(){
System.out.println("Welecome! "+name);
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public static void main(String[] args) throws Exception {
//获得类信息
Class cl = Class.forName("reflect.Employee");
//获得“sayHello"方法
Method m1 = cl.getMethod("sayHello", null);
//调用sayHello方法
m1.invoke(cl.newInstance(), null);
//获得“sayName”方法
Method m2 = cl.getMethod("sayName", null);
//调用sayName方法,static 方法不用传递实例
m2.invoke(null, null);
//获得“getName”方法
Method m3 = cl.getMethod("getName", null);
//调用“getName”方法
String name = (String)m3.invoke(cl.newInstance(), null);
System.out.println(name);
//获得“setName”方法,后一个参数为参数的类信息
Method m4 = cl.getMethod("setName", String.class);
m4.invoke(cl.newInstance(), "tjy_521");
//调用“getName”方法
name = (String)m3.invoke(cl.newInstance(), null);
System.out.println(name);
}
}
输出结果:
Hello
Welecome! tjy
tjy
tjy_521
反射工具类库还有很多其他的类,由于一个类,我们最关心的还是它的属性及行为,所以,在这里,我就只介绍了Class、Field、Method这几个简单的类及常用的方法,请各位具体用到的时候在深入了解。