反射详细说明

反射概述

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。

在运行时,可以直接得到这个类的构造器对象:Constructor。

在运行时,可以直接得到这个类的成员变量对象:Field。

在运行时,可以直接得到这个类的成员方法对象:Method。

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

反射获取类对象

三种方式获取类对象

 

反射获取构造器对象并使用

Constructor<?>[] getConstructors​()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[] getDeclaredConstructors​()返回所有构造器对象的数组,存在就能拿到
Constructor<T> getConstructor​(Class<?>... parameterTypes)返回单个构造器对象(只能拿public的)
Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes)返回单个构造器对象,存在就能拿到

Constructor类中用于创建对象的方法 

T newInstance​(Object... initargs)根据指定的构造器创建对象
public void  setAccessible(boolean flag)对于非public构造器需要设置为true,表示取消访问检查,进行暴力反射

反射获取成员变量对象并使用

Field[] getFields​()返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields​()返回所有成员变量对象的数组,存在就能拿到
Field getField​(String name)返回单个成员变量对象(只能拿public的)
Field getDeclaredField​(String name)返回单个成员变量对象,存在就能拿到

使用成员变量

void set​(Object obj, Object value)赋值
Object get​(Object obj)获取值
public void  setAccessible(boolean flag)对于非public成员变量需要设置为true,表示取消访问检查,进行暴力反射

反射获取方法对象并使用

Method[] getMethods​()返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods​()返回所有成员方法对象的数组,存在就能拿到
Method getMethod​(String name, Class<?>... parameterTypes)返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod​(String name, Class<?>... parameterTypes)返回单个成员方法对象,存在就能拿到

 使用Method对象

Object invoke​(Object obj, Object... args)

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

public void  setAccessible(boolean flag)对于非public成员方法对象需要设置为true,表示取消访问检查,进行暴力反射

反射的作用-绕过编译阶段为集合添加数据

 如下代码在编译阶段是通不过的:

ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(“黑马"); // 报错
list.add(99);

 而泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。那么我们就可以用反射技术为该集合添加字符串,因为反射技术就是在运行阶段运用的。如下所示:

        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        //list.add("黑马"); // 报错
        list.add(99);

        Class<? extends ArrayList> listClass = list.getClass();
        Method add = listClass.getDeclaredMethod("add", Object.class);
        add.invoke(list,"heima");
        System.out.println(list);

反射的作用-通用框架的底层原理

需求:给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文件中去。

 分析

定义一个方法,可以接收任意类的对象。

每次收到一个对象后,需要解析这个对象的全部成员变量名称。

这个对象可能是任意的,那么怎么样才可以知道这个对象的全部成员变量名称呢?

使用反射获取对象的Class类对象,然后获取全部成员变量信息。

遍历成员变量信息,然后提取本成员变量在对象中的具体值

存入成员变量名称和值到文件中去即可。

代码:

public static void save(Object obj){

        try (
                PrintStream ps = new PrintStream(
                new FileOutputStream("E:\\data.txt",true));
             ){
            Class<?> objClass = obj.getClass();
            Field[] fields = objClass.getDeclaredFields();
            ps.println("==="+objClass.getSimpleName()+"===");
            for (Field field : fields) {
                field.setAccessible(true);
                String name = field.getName();
                String value = field.get(obj)+"";
                ps.println(name + "="+value);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

总结

反射的作用?

可以在运行时得到一个类的全部成分然后操作。

可以破坏封装性。(很突出)

也可以破坏泛型的约束性。(很突出)

更重要的用途是适合:做Java高级框架

基本上主流框架都会基于反射设计一些通用技术功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值