java基础中的反射机制

来源:互联网 发布:杭州java培训有用 编辑:程序博客网 时间:2024/06/08 15:30

目的:为了了解注解式框架的原理 ViewInject bindView Retrofit2等,里面都用到了注解,底层都是通过反射实现的


什么是java中的反射机制?

通过Class对象,获取字节码文件中的成员变量,构造方法,普通方法的机制

1)反射机制是对类而言的,目的是为了获取类的所有属性和方法

Java反射机制实在程序运行状态中,对于任意一个类,都能知道这个类的所有的属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象方法的功能就是java语言的反射机制。

2)要想使用反射,必须知道该类的字节码文件对象(对应类的字节码文件)

3)如何获取字节码文件对应的类对象?


反射机制中常用的类及方法:(总共四个类)

Method类 Class类 Constructor构造函数类 Field字段类

forName("全类名");   获取字节码文件对象

getConstructor()  获取指定类型的构造函数 注意s

newInstance()  通过构造函数创建对象,构造方法将会被执行!

getField() 获取成员变量

getMethod(name,参数类型) 获取的方法的名称,和方法的参数类型

invoke(当前类的对象,方法的参数)  通过反射获取的方法如何执行 Method类对象调用的方法

method.setAccessible(true);


getDeclaredConstructor() 获取私有的构造函数

getDeclaredMethod()  获取私有的成员方法

getDeclaredField() 获取私有的成员变量


get()方法

set()

修改成员的值:set(Object obj,Object value)
将指定对象变量上此成员变量对象表示的字段值设置为指定的新值。


反射一般的操作步骤:

1)通过全类名,获取类对象,即类的字节码文件的操作

2)通过类对象,获取类的构造函数

3)通过构造函数,创建对象

4)通过对象,执行其中的方法


1)通过反射获取构造方法并使用

2)通过反射获取成员变量并使用

3)通过反射获取成员方法并使用

4)如果是私有的,就“Declared”+“暴力破解”


特点:

反射机制其实就是学习这四个类的api,反射是一种编程思想.

通过反射机制可以越过泛型检查,向集合中存储不同类型的数据.

泛型是用作编译器检查的,看看是不是有语法错误.

类名.class,可以获取类的字节码文件,即可以获取类对象.

反射是动态的,所以需要处理很多异常.


package com.crs.demo.ui.reflect;import java.lang.reflect.Constructor;/** * Created on 2016/9/21. * Author:crs * Description:反射demo * 通过Class对象,获取字节码文件中的成员变量,构造方法,普通方法的操作 * 1)通过全类名获取字节码文件对象 * 2)获取指定的构造函数 * 3)通过构造创建对象 */public class ReflectDemo {    private static Class mClass;    private static Constructor constructor;    public static void main(String[] args) {        //1)获取Class对象        try {            mClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");        } catch (Exception e) {            e.printStackTrace();        }        //2)通过反射获取无参数构造函数并使用        //a:获取构造函数数组,但是不能够获取私有的构造方法        Constructor[] array = mClass.getConstructors();        for (Constructor con : array) {            //能够获取公有的构造方法            //System.out.print(con);        }        //b:能够获取所有的构造方法,包括私有的        Constructor[] arrayPrivate = mClass.getDeclaredConstructors();        for (Constructor con : arrayPrivate) {            //System.out.print(con);        }        //c:如何获取指定的某一个构造方法(获取空参数构造方法)        //public Constructor<T> getConstructors(Class < ? >...params)        //参数类型是你要获取的构造方法中的参数的class类型即可        try {            //这个构造方法获取不到,因为是私有的.            //Constructor constructors1 = mClass.getConstructor(String.class);            constructor = mClass.getConstructor(null);        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        //d:如何通过拿到的构造方法,创建对象  这个方法的返回结果为泛型        try {            Object o = constructor.newInstance();            System.out.print(o.toString());        } catch (Exception e) {            e.printStackTrace();        }    }}

package com.crs.demo.ui.reflect;import android.support.v4.view.ViewCompat;import java.lang.reflect.Constructor;import java.lang.reflect.Field;/** * Created on 2016/9/22. * Author:crs * Description: * 1)通过反射获取构造方法并使用 * 2)通过反射获取成员变量并使用 * 3)通过反射获取成员方法并使用 * 3)如果是私有的,就“Declared”+“暴力破解” */public class ReflectDemo1 {    public static void main(String[] args) {        //1需求:通过反射获取公共的有参数构造函数,并创建对象        try {            Class c = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            Constructor con = c.getConstructor(String.class, int.class, String.class);            Object obj = con.newInstance("陈如水", 22, "上海市徐汇区");            System.out.print(obj.toString() + "\n");        } catch (Exception e) {            e.printStackTrace();        }        //2需求:获取私有的构造方法,并创建对象使用        try {            Class aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            Constructor cons = aClass.getDeclaredConstructor(String.class);            //私有的构造方法,可以通过暴力访问来破解java中的权限访问修饰符            cons.setAccessible(true);//调用此方法,开启暴力访问            Object object = cons.newInstance("守望江湖");            System.out.print(object.toString() + "\n");        } catch (Exception e) {            e.printStackTrace();        }        //3需求:通过反射获取公有的成员变量,并使用        try {            Class<?> aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            //获取成员变量字节数组            Field[] fields = aClass.getFields();            for (Field f : fields) {                System.out.print(f + "\n" + "\n");                //能够拿到公有的字段name            }        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        //4需求:通过反射获取所有的成员变量,并使用        try {            Class<?> aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            Field[] declaredFields = aClass.getDeclaredFields();            for (Field field : declaredFields) {                System.out.print(field + "\n" + "\n");            }        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        //5需求:通过反射获取指定的成员变量,并进行赋值操作        try {            Class aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            Constructor constructor = aClass.getConstructor(null);            Object o = constructor.newInstance();            Field name = aClass.getField("name");            name.set(o, "chen");            System.out.print(o.toString() + "\n");        } catch (Exception e) {            e.printStackTrace();        }        //5需求:通过反射获取私有的成员变量,并进行赋值操作(Declared,暴力破解)  set()方法  反射独有的        try {            Class aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            //获取对象            Constructor constructor = aClass.getConstructor(null);            Object object = constructor.newInstance();            //获取私有字段            Field age = aClass.getDeclaredField("age");            age.setAccessible(true);            //给字段设置值            age.set(object, 33);            System.out.print(object.toString() + "\n");        } catch (Exception e) {            e.printStackTrace();        }        //6需求:通过反射当前字段的值  get()方法  反射独有的        try {            Class aClass = Class.forName("com.crs.demo.ui.reflect.PersonEntity");            Constructor constructor = aClass.getConstructor(null);            Object object = constructor.newInstance();            Field address = aClass.getDeclaredField("address");            address.setAccessible(true);            address.set(object, "碧云天,黄叶地,秋色连波,波上寒烟翠!");            //获取值            Object addObject = address.get(object);            System.out.print(addObject.toString() + "\n");        } catch (Exception e) {            e.printStackTrace();        }    }}

package com.crs.demo.ui.reflect;import java.lang.reflect.Method;import java.util.ArrayList;/** * Created on 2016/9/22. * Author:crs * Description:通过反射机制越过泛型检查 */public class ReflectDemo3 {    public static void main(String[] args) {        //泛型约束是编译期的语法检查        ArrayList<Integer> list = new ArrayList<>();        list.add(1);        list.add(2);        //如何通过泛型向list集合中添加"陈如水"呢?        try {            //在集合中可以存储Object类型的            Class aClass = Class.forName("java.util.ArrayList");            Method add = aClass.getMethod("add", Object.class);            add.invoke(list,"陈如水");            System.out.print(list);            //打印结果:[1, 2, 陈如水]        } catch (Exception e) {            e.printStackTrace();        }    }}



3 0