反射
能够分析类能力的程序被称为反射。反射机制可以用来:
- 在运行时分析类;
- 在运行时查看对象;
- 实现通用的数组操作代码;
- 使用
Method
对象,以类似于函数指针的方式调用函数。
通过反射分析类
public class ReflectionTest {
public static void main(String[] args) {
String name;
if (args.length > 0)
name = args[0];
else {
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date): ");
name = in.next();
}
try {
Class cls = Class.forName(name);
Class superCls = cls.getSuperclass();
String modifiers = Modifier.toString(cls.getModifiers());
if (modifiers.length() > 0)
System.out.print(modifiers + " ");
System.out.print("class " + cls.getName());
if (superCls != null && superCls != Object.class)
System.out.print(" extends " + superCls.getName());
System.out.println("\n{");
showConstructor(cls);
System.out.println();
showFields(cls);
System.out.println();
showMethods(cls);
System.out.println("}");
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
}
private static void showConstructor(Class cls){
Constructor[] constructors=cls.getDeclaredConstructors();
for(Constructor constructor:constructors){
String name=constructor.getName();
System.out.print("\t");
String modifiers=Modifier.toString(constructor.getModifiers());
if(modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.print(name+"(");
Class[] paramTypes=constructor.getParameterTypes();
for(int i=0;i<paramTypes.length;i++){
if(i<paramTypes.length-1)
System.out.print(paramTypes[i].getName()+", ");
else
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
private static void showFields(Class cls){
Field[] fields=cls.getDeclaredFields();
for(Field field:fields){
Class type=field.getType();
String name=field.getName();
String modifiers=Modifier.toString(field.getModifiers());
System.out.print("\t");
if(modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+name+";");
}
}
private static void showMethods(Class cls){
Method[] methods=cls.getDeclaredMethods();
for(Method method:methods){
String name=method.getName();
String modifiers=Modifier.toString(method.getModifiers());
System.out.print("\t");
if(modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.print(name+"(");
Class[] paramTypes=method.getParameterTypes();
for(int i=0;i<paramTypes.length;i++){
if(i<paramTypes.length-1){
System.out.print(paramTypes[i].getName()+", ");
}
else
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
}
上述程序会打印出输入类(如java.lang.String)的所有constructors,fields,methods(反射方法名中的Declared表明只获取本类中的信息,而不包括父类)。
通过反射查看对象
public class Test {
public static void main(String[] args) throws Exception {
ReflectField testObj=new ReflectField("han feng");
Class cls=testObj.getClass();
Field mask=cls.getDeclaredField("mask");
Object v=mask.get(testObj);
System.out.println(v);//反射机制获取实例的特定域值
System.out.println(testObj.mask);//传统方法
}
}
class ReflectField{
public String mask;
public ReflectField(String mask){
this.mask=mask;
}
}
通过反射操作数组
通过一个数组扩容的例子来说明反射机制在数组上的使用。
public static Object goodCopyOf(Object a,int newLength){//a is an array
Class cls=a.getClass();
if(!cls.isArray())return null;
Class componentType=cls.getComponentType();
int length=Array.getLength(a);
Object newArray=Array.newInstance(componentType,newLength);
Arrays.copy(a,0,newArray,0,Math.min(length,newLength));
return newArray;
}
函数goodCopyOf()
数组参数a的类型设置为Object的原因在于:int[]可以转化为 Object,但是不能转化为Object[],这样该函数的泛型能力更强。
通过反射使用方法
public class Test {
public static void main(String[] args) throws Exception {
ReflectMethod testObj=new ReflectMethod();
Class cls=testObj.getClass();
Method hello=cls.getDeclaredMethod("hello",String.class);
Method introduce=cls.getDeclaredMethod("introduce");
hello.invoke(testObj,"I love you.");//通过反射调用实例方法
introduce.invoke(null);//通过反射调用类方法
}
}
class ReflectMethod{
public void hello(String message){
System.out.println("he said:\""+message+"\"");
}
public static void introduce(){
System.out.println("My name is "+ReflectMethod.class.getName());
}
}