你的位置:首页 > Java教程

[Java教程]Java反射的理解


反射的作用:
 
1.运行时检查类的结构
2.运行时更改类的字段值
3.调用类的方法
 
准备知识:
 
Class类:虚拟机为每一个对象保存的一份对象所属类的清单:
static Class forName(String className) 获取字符串(接口或者类的全类名)对应的类的Class对象。
Object newInstance() 返回Class对应的类的一个对象
 
解析: 
1.运行时检查类的结构
    java.lang.reflection 中有三个类:
    1.Field 对应类的字段
        getName() 返回Field对应的名称
        getType() 返回Field所在的Class类型
    2.Method 对应类的方法
        getName() 返回Method 对应的名称
        Class<?>[] getParameterTypes() 按方法声明的顺序返回参数类型数组
        int getModifiers() 返回一个整数值,用不同的位开关表示static,public这样的修饰情况。
    3.Constructor 对应构造器
        getName() 返回Constructor 对应的名称
        Class<?>[] getParameterTypes() 按方法声明的顺序返回参数类型数组
        int getModifiers() 返回一个整数值,用不同的位开关表示static,public这样的修饰情况。
 
在Method和Constructor中可以使用Modifier类的isPrivate,isStatic 来判断getModifiers()的返回值,给出是否含有对应的修饰符。
Class对象的getDeclaredConstructors,getDeclaredMethods,getDeclaredFields分别用于获取对象的构造器,方法,字段,以数组的形式返回。
 
下面为反射基本用法:检测一个类的结构:
 
 1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Modifier; 5  6 //反射基本测试 7 public class ReflectionTest { 8   public static void main(String[] args) { 9     String name = "java.util.Date";10     try {11       Class cl = Class.forName(name);12       Class supercl = cl.getSuperclass();13       String modifiers = Modifier.toString(cl.getModifiers());14       if (modifiers.length() > 0) System.out.print(modifiers + " ");15       System.out.print("class " + name);16       if (supercl != null && supercl != Object.class) System.out.print(" extends "17           + supercl.getName());18 19       System.out.print("\n{\n");20       printConstructors(cl);21       System.out.println();22       printMethods(cl);23       System.out.println();24       printFields(cl);25       System.out.println("}");26     } catch (ClassNotFoundException e) {27       e.printStackTrace();28     }29     System.exit(0);30   }31 32 33   public static void printConstructors(Class cl) {34     Constructor[] constructors = cl.getDeclaredConstructors();35 36     for (Constructor c : constructors) {37       String name = c.getName();38       System.out.print("  ");39       String modifiers = Modifier.toString(c.getModifiers());40       if (modifiers.length() > 0) System.out.print(modifiers + " ");41       System.out.print(name + "(");42 43       // print parameter types44       Class[] paramTypes = c.getParameterTypes();45       for (int j = 0; j < paramTypes.length; j++) {46         if (j > 0) System.out.print(", ");47         System.out.print(paramTypes[j].getName());48       }49       System.out.println(");");50     }51   }52 53 54   public static void printMethods(Class cl) {55     Method[] methods = cl.getDeclaredMethods();56 57     for (Method m : methods) {58 59       Class retType = m.getReturnType();60       String name = m.getName();61 62       System.out.print("  ");63       // print modifiers, return type and method name64       String modifiers = Modifier.toString(m.getModifiers());65       if (modifiers.length() > 0) System.out.print(modifiers + " ");66       System.out.print(retType.getName() + " " + name + "(");67 68       // print parameter types69       Class[] paramTypes = m.getParameterTypes();70       for (int j = 0; j < paramTypes.length; j++) {71         if (j > 0) System.out.print(", ");72         System.out.print(paramTypes[j].getName());73       }74       System.out.println(");");75     }76   }77 78 79   public static void printFields(Class cl) {80     Field[] fields = cl.getDeclaredFields();81 82     for (Field f : fields) {83       Class type = f.getType();84       String name = f.getName();85       System.out.print("  ");86       String modifiers = Modifier.toString(f.getModifiers());87       if (modifiers.length() > 0) System.out.print(modifiers + " ");88       System.out.println(type.getName() + " " + name + ";");89     }90   }91 }

 

 

2.更改类的字段值:
    Field对象有以下对应的一系列方法:
    public Object get(Object obj) 获取目标对象上字段的值
    public void set(Object obj, Object value)设置目标对象上字段的值
    有相应具体类型的get和set方法。
 
3.调用类的方法(类似于方法指针):
    Method对象方法:
     public Object invoke(Object obj, Object... args)
    obj是调用的目标对象,ars是方法参数
 
以下为示例代码:
 1 import java.lang.reflect.Field; 2 import java.lang.reflect.InvocationTargetException; 3 import java.lang.reflect.Method; 4  5 /** 6  * Created by karlx on 2015/5/29. 7 */ 8 public class ReflectionTest2 { 9   public static void main(String[] args) {10     Person person = new Person();11     person.name = "karl";12     //获取,设置 运行中对象的字段值13     Class clazz = person.getClass();14     try {15       Field field = clazz.getField("name");16       field.setAccessible(true);//避开java的访问检查17       System.out.println(field.get(person));18 19       field.set(person, "xiaoming");20       System.out.println(field.get(person));21 22     } catch (NoSuchFieldException | IllegalAccessException e) {23       e.printStackTrace();24     }25     //运行中调用对象的方法26     try {27       Method method = clazz.getMethod("getName");28       method.setAccessible(true);//避开java的访问检查29       System.out.println(method.invoke(person));30     } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {31       e.printStackTrace();32     }33   }34 35   static class Person {36     public String name;37 38     public String getName() {39       return name + "hello";40     }41 42     public void setName(String name) {43       this.name = name;44     }45   }46 }