1.1 JAVA反射
反射 (Reflection) ,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1.2 JAVA自省
内省 (Introspector),是“看透class”的能力(内省、内观、反省)。
2 class结构
2.1 “Class” object的取得途径
Java允许我们从多种管道为一个class生成对应的Class object。
Class object 诞生管道
|
示例
|
运用getClass()
注:每个class 都有此函数
|
String str = "abc";
Class c1 = str.getClass();
|
运用
Class.getSuperclass()2
|
Button b = new Button();
Class c1 = b.getClass();
Class c2 = c1.getSuperclass();
|
运用static method
Class.forName()
(最常被使用)
|
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName ("java.util.LinkedList$Entry");
Class c4 = Class.forName ("I");
Class c5 = Class.forName ("[I");
|
运用
.class 语法
|
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
|
运用
primitive wrapper classes
的TYPE 语法
|
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
|
图1:Java 允许多种管道生成Class object。
2.2 Java classes 组成分析
以图2的java.util.LinkedList为例,将Java class的定义大卸八块,每一块分别对应图3所示的Reflection API。
package java.util; //(1)
import java.lang.*; //(2)
public class LinkedList<E> //(3)(4)(5)
extends AbstractSequentialList<E> //(6)
implements List<E>, Queue<E>,
Cloneable, java.io.Serializable //(7)
{
private static class Entry<E> { … }//(8)
public LinkedList() { … } //(9)
public LinkedList(Collection<? extends E> c) { … }
public E getFirst() { … } //(10)
public E getLast() { … }
private transient Entry<E> header = …; //(11)
private transient int size = 0;
}
图2:将一个Java class 大卸八块,每块相应于一个或一组Reflection APIs(图3)。
2.3 Java classes 各成份所对应的Reflection APIs
图2的各个Java class成份,分别对应于图3的Reflection API,其中出现的Package、Method、Constructor、Field等等classes,都定义于java.lang.reflect。本表并非Reflection APIs 的全部。
Java class 内部模块(参见图3)
|
Java class 内部模块说明
|
相应之Reflection API,多半为Class methods。
|
返回值类型(return type)
|
(1) package
|
class隶属哪个package
|
getPackage()
|
Package
|
(2) import
|
class导入哪些classes
|
无直接对应之API。
解决办法见图5-2。
|
|
(3) modifier
|
class(或methods, fields)的属性
|
int getModifiers()
Modifier.toString(int)
Modifier.isInterface(int)
|
int
String
bool
|
(4) class name or interface name
|
class/interface
|
名称getName()
|
String
|
(5) type parameters
|
参数化类型的名称
|
getTypeParameters()
|
TypeVariable <Class>[]
|
(6) base class
|
base class(只可能一个)
|
getSuperClass()
|
Class
|
(7) implemented interfaces
|
实现有哪些interfaces
|
getInterfaces()
|
Class[]
|
(8) inner classes
|
内部classes
|
getDeclaredClasses()
|
Class[]
|
(8') outer class
|
如果我们观察的class 本身是inner classes,那么相对它就会有个outer class。
|
getDeclaringClass()
|
Class
|
(9) constructors
|
构造函数getDeclaredConstructors()
|
不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Constructor[]
|
(10) methods
|
操作函数getDeclaredMethods()
|
不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Method[]
|
(11) fields
|
字段(成员变量)
|
getDeclaredFields()不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Field[]
|
图3:Java class大卸八块后(如图2),每一块所对应的Reflection API。
3 Java例程
Model.java
package RefInt;
import java.io.Serializable;
import java.util.Date;
publicclass Model implements Serializable {
privatestaticfinallongserialVersionUID = -162798607158235676L;
publicstatic String id = "111111";
public String name = "haha";
privateintage ;
private Date b;
publicint getAge() {
returnage;
}
publicvoid setAge(int age) {
this.age = age;
}
public Date getB() {
returnb;
}
publicvoid setB(Date b) {
this.b = b;
}
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
}
RefInt.java
package RefInt;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
publicclass RefInt {
publicstaticvoid main(String[] args) {
System.out.println("f_1()");
f_1();
System.out.println("f_2()");
f_2();
System.out.println("f_3()");
f_3();
System.out.println("f_4()");
f_4();
System.out.println("getArrayByIndex()");
int[] a = {10,2,3,5};
String[] s = {"aabc","aaabc","def","f"};
// 数组排序
Arrays.sort(s);
System.out.println(getArrayByIndex(s,0));
System.out.println(getArrayByIndex(a,0));
System.out.println(getArrayByIndex(a,3));
Arrays.sort(a);
System.out.println(getArrayByIndex(a,0));
System.out.println(getArrayByIndex(a,3));
Array.set(a, 0, -1);
System.out.println(getArrayByIndex(a,0));
}
/**
*获得数组o下标为index的值
*@paramo
*@paramindex
*@return
*/
publicstatic Object getArrayByIndex(Object o , int index) {
return Array.get(o, index);
}
/**
*通过类名得到类描述对象
*通过类描述对象获得类模式(此类为public)
*/
publicstaticvoid f_4() {
try {
Class class_my = Class.forName("RefInt.Model");
int m = class_my.getModifiers();
System.out.println(class_my.getModifiers());
if (Modifier.isPublic(m))
System.out.println("public");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
/**
*通过类名得到类描述对象
*通过类描述对象获得属性对象列表并显示其属性
*/
publicstaticvoid f_3() {
try {
Class class_my = Class.forName("RefInt.Model");
// 只能得到属性是public的Field
Field[] publicFields = class_my.getFields();
for (int i = 0; i < publicFields.length; i++) {
String fieldName = publicFields[i].getName();
Class typeClass = publicFields[i].getType();
String fieldType = typeClass.getName();
System.out.println("Name: " + fieldName + ", Type: " + fieldType);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
*通过实体对象获得类描述对象
*通过累描述对象获得指定属性对象
*通过属性对象实例得到属性名和属性值
*/
publicstaticvoid f_2() {
Model model = new Model();
//属性必须是public,否则抛出NoSuchFieldException异常
String sfiled = "name";
Class class_my = model.getClass();
try {
Field filed = class_my.getField(sfiled);
System.out.println(filed.getName());
System.out.println(filed.get(model));
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
*通过类名获得实体对象
*通过属性名称获取实体对象属性值
*/
publicstaticvoid f_1() {
try {
Class cla = Class.forName("RefInt.Model");
Object o = cla.newInstance();
String methodName = "getName";
Method m = cla.getMethod(methodName, (Class[])null);
System.out.println(m.invoke(o, (Object[])null));
methodName = "getAge";
m = cla.getMethod(methodName, (Class[])null);
System.out.println(m.invoke(o, (Object[])null));
methodName = "getB";
m = cla.getMethod(methodName, (Class[])null);
System.out.println(m.invoke(o, (Object[])null));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
Intro.java
package RefInt;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
publicclass Intro {
publicstaticvoid main(String[] args) {
Model m = new Model();
try {
// 从其所在位置开始停止分析的基类。stopClass 或其基类中的所有方法/属性/事件都将在分析中被忽略。
BeanInfo beanInfor = Introspector.getBeanInfo(m.getClass(),Object.class);
PropertyDescriptor[] p = beanInfor.getPropertyDescriptors();
for(int i=0;i<p.length;i++){
System.out.println(p[i].getName()+"="+
p[i].getReadMethod().invoke(m,(Object[])null));
}
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}