Java反射机制

1.1 反射机制的定义

在运行状态中,对于任意一个类,都可以获取类的方法和属性;对于任意一个对象,都可以调用对象的方法。这种动态地获取类信息或者动态地调用对象的方法的功能就叫做类的反射机制。

1.2 java.lang.Class

在Java程序运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,这项信息记录对象所属的类。虚拟机将会根据运行时类型信息选择正确的方法执行,用来保存这项信息的类便是Class类。
当ClassLoader找到需要调用的类时,就会加载它,并根据.class文件中记载的信息来产生一个独一无二的Class实例,该Class实例保存了该类的方法、字段等信息。以后JVM需要产生该类的实例时,就是根据内存中Classs实例的相关信息来进行。
1. Class是一个类,一个描述类的类,封装了描述方法的Method,描述字段的Field,描述构造器的Constructor等属性;
2. 通过反射可以得到某个类的数据成员名、方法、构造器以及它实现了哪些接口;
3. Class类的对象只能由系统来创建,一个类在JVM只有一个Class类实例;

1.2.1 Class对象的获取方式

Class对象可以通过以下方式获取:

//1. 通过Object类的getClass()方法
Main0 t=new Main0();
Class c=t.getClass();

//2. 通过Class类的静态方法ofrName("完全限定名(即:包名+类名)")方法
Class c2=Class.forName("com2.Main0");

//3. 每一个类都有class属性
Class c3=Main0.class;
1.2.2 Class类的常用方法
1. 创建对象

在获取Class类对象后,可以通过newInstance方法来创建Class对象对应类的对象,需要强调的是,newInstance调用的是类的默认构造函数,所以当使用newInstance方法时,必须保证Class对象对应的类中包含无参数构造函数;

Class c2=Class.forName("com2.Main0");
Object o=c2.newInstance();   //调用Main0类的默认构造函数
2. 获取成员属性

获取成员属性的方法分为两大类:一类是获取所有的属性,另外一类是根据名字获取特定的属性。
2.1 获取所有属性方法有两个,如下所示:

//该方法将会返回包含所有public属性的Field数组
//如果Class对象代表的类是一个类或者接口,它不包含public属性,那么返回数组的长度为0;
//如果Class对象代表的是一个数组或者原始类型(如int),那么返回数组的长度为0;
//如果Class对象代表一个类,那么将会返回当前类和继承而来的所有public属性;
//如果Class对象代表一个接口,那么将会返回当前接口和所有扩展接口中的属性;
public Field[] getFields();

//该方法同样会返回一个Field对象的数组
//该方法返回的Field对象数组为Class对象所代表的类中包括publicprotectedprivatedefault修饰的属性,但是不包含继承而来的属性;
public Field[] getDeclaredFields();

上述两个方法的应用示例如下:

//getFields方法的示例
public static void printFields(Class c){
        Field[] fields=c.getFields();
        StringBuffer sb=new StringBuffer();
        sb.append(Modifier.toString(c.getModifiers())+"\t"+c.getSimpleName()+"{\n");
        for(Field field:fields){
            sb.append("\t"+Modifier.toString(field.getModifiers()));  //获取属性修饰符
            sb.append("\t"+field.getType().getSimpleName());  //获取属性类型
            sb.append("\t"+field.getName());  //获取属性名
            sb.append(";\n");
        }
        sb.append("}\n");
        System.out.println(sb);
    }


//getDeclaredFields方法示例
public static void printFields(Class c){
        Field[] fields=c.getDeclaredFields();
        StringBuffer sb=new StringBuffer();
        sb.append(Modifier.toString(c.getModifiers())+"\t"+c.getSimpleName()+"{\n");
        for(Field field:fields){
            sb.append("\t"+Modifier.toString(field.getModifiers()));  //获取属性修饰符
            sb.append("\t"+field.getType().getSimpleName());  //获取属性类型
            sb.append("\t"+field.getName());  //获取属性名
            sb.append(";\n");
        }
        sb.append("}\n");
        System.out.println(sb);
}

2.2 根据名字获取特定属性的方法同样有两个,如下:

//该方法返回一个Field对象,该Field对象反射了name所指定的public属性
//第一步,该方法在当前类中查找是否存在name指定的public属性;
//第二步,如果在第一步中没有找到,那么将会从当前类所直接实现的接口中查找name指定的属性,查找接口顺序按照声明接口的顺序;
//第三步,如果在第二部中还没有找到,那么将会递归地从当前类的父类中查找;
//如果上述过程均未找到,那么将会抛出NoSuchFieldException异常
public Field getField(String name)

//返回Class对象所代表的类中指定name的Field对象
//如果没有找到,将会抛出NoSuchFieldException异常
public Field getDeclaredField(String name)

上述两个方法的示例如下:

//getField(String name)方法示例
public static void printSpecificFields(Class c,String name) throws Exception{
        Field field=c.getDeclaredField(name);
        StringBuffer sb=new StringBuffer();

        sb.append(Modifier.toString(field.getModifiers()));  //获取属性修饰符
        sb.append("\t"+field.getType().getSimpleName());  //获取属性类型
        sb.append("\t"+field.getName());  //获取属性名
        sb.append(";\n");

        System.out.println(sb);
}
3. 获取成员方法

获取成员方法的函数也分为两类:一类是获取所有方法,另一类是根据参数获取特定的方法;

3.1 获取所有成员方法的函数有两个,如下:

//返回反射出Class对象所代表的类中所有public方法的Method数组,递归遍历其父类直至Obejct类中的所有public方法
public Method[] getMethods()

//返回Class对象所代表的类中声明的publicprotectedprivatedefault方法,但是不包含继承而来的方法
public Method[] getDeclaredMethods()

上述两个方法的应用示例如下:

//getMethods方法示例
public static void printMethods(Class c){
        Method[] methods=c.getMethods();
        StringBuffer sb=new StringBuffer();
        sb.append(Modifier.toString(c.getModifiers())+"\t"+c.getSimpleName()+"{\n");
        for(Method method:methods){
            sb.append("\t"+Modifier.toString(method.getModifiers())+"\t");
            sb.append(method.getReturnType().getSimpleName()+"\t");
            sb.append(method.getName()+"()\n");
        }
        sb.append("}\n");
        System.out.println(sb);
    }

//getDeclaredMethods方法示例
    public static void printMethods(Class c){
        Method[] methods=c.getDeclaredMethods();
        StringBuffer sb=new StringBuffer();
        sb.append(Modifier.toString(c.getModifiers())+"\t"+c.getSimpleName()+"{\n");
        for(Method method:methods){
            sb.append("\t"+Modifier.toString(method.getModifiers())+"\t");
            sb.append(method.getReturnType().getSimpleName()+"\t");
            sb.append(method.getName()+"()\n");
        }
        sb.append("}\n");
        System.out.println(sb);
    }

3.2 获取特定方法函数有两个,如下:

//返回反射出Class对象所代表的类中指定public方法的Method对象
//name参数代表方法的名字
//parameterTypes参数代表方法的指定参数类型次序
//如果在当前类中没有找到,递归地从父类中查找指定的方法;
public Method getMethod(String name, Class<?>... parameterTypes)


//从Class对象所代表的类中返回指定的方法所对应的Method对象
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

上述两个方法的示例如下:

//getMethod(String name, Class<?>... parameterTypes)方法示例
public static void invokeSpecialMethod(Class<?> c,String methodName,Object[] args){
        Class<?>[] argsClasses=new Class<?>[args.length];
        for(int i=0;i<args.length;i++){
            argsClasses[i]=args[i].getClass();
        }
        try{
            Method method=c.getMethod(methodName, argsClasses);
            Object o=c.newInstance();
            method.invoke(o, args);
        }catch(Exception e){
            System.out.println("getMethod error");
        }
    }

//getDeclaredMethod(String name, Class<?>... parameterTypes)方法示例
public static void invokeSpecialMethod(Class<?> c,String methodName,Object[] args){
        Class<?>[] argsClasses=new Class<?>[args.length];
        for(int i=0;i<args.length;i++){
            argsClasses[i]=args[i].getClass();
        }
        try{
            Method method=c.getDeclaredMethod(methodName, argsClasses);
            Object o=c.newInstance();
            method.invoke(o, args);
        }catch(Exception e){
            System.out.println("getMethod error");
        }
    }
4. 其他

待续。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值