java基础中的反射机制

目的:为了了解注解式框架的原理 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值