博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java中的反射整理
阅读量:4326 次
发布时间:2019-06-06

本文共 6214 字,大约阅读时间需要 20 分钟。

1,什么是反射

反射机制是java语言提供的一种基础功能,它能够赋予成语在运行时进行自省的能力。通过反射我们可以直接操作类或者对象,例如:可以通过反射去获取某个对象的类的定义,属性,方法,还可以修改类的定义。

2,反射中的包

2.1反射包

java中专门的反射包java.lang.reflect,反射包下包含了很多类,具体可以参考jdk,这里我们用到的有Field类的成员变量,Method方法,Constructor构造器。

2.2AccessibleObject

关于反射有一点需要特意注意一下,就是反射包提供的AccessibleObject类中的setAccessible方法。

他的子类很多也重写了这个方法,这里的所谓的setAccessible顾名思义,就是指的是成员变量前面的用于修饰的public、protected、private,这个方法也就意味着我们可以在运行时通过反射去修改类的成员变量的访问限制。

setAccessible的应用场景非常广泛,各种框架:开发、测试、依赖注入。例如在数据库O/R Mapping框架中,我们在加载或者持久化数据的时候,框架通常会利用反射做这个事情,而不需要开发者自己去实现。

还有个典型的应用场景,就是绕过API的访问控制。我们在开发的过程中,有时候,可能需要调用内部的API去做一些事情,比如,自定义的高性能的NIO框架需要显示的释放DirectBuffer,使用反射绕开限制是一种常见的办法。

2.2Modifier

反射包中还有一个重要的类Modifier,该类是静态类,其中的方法也是静态方法。 

Modifier.Class类中getModifiers()函数返回一个用于描述类,构造器,方法和域的修饰符的整形数值。、 
调用Modifier.toString()方法将整型数值转变成字符串,也是就我们熟悉的public,private,static,final等修饰符。

2.3代码实例

/** * 创建一个user类 * 可不在与main方法同一个类中创建 */class User{    //定一个成员变量:姓名    private String name;    //无参构造    public User(){}    //有参构造    public User(String name) {        this.name = name;    }    //get方法    public String getName() {        return name;    }    //set方法    public void setName(String name) {        this.name = name;    }}
/** * 测试Class类的函数和反射库中的函数 */public class TestReflectController {    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {        //获得User类的Class对象        Class
cc = User.class; //下面这个是通过new出来的对象,并通过set给成员变量赋值 User user1 = new User(); user1.setName("hello"); //下面这个是通过构造器的方式 //1.有参构造器 //先得到有参构造器的信息,再根据构造器的信息,由newInstance()函数创建一个User对象 Constructor
constructor = cc.getConstructor(String.class); //这个constructor.newInstance方法就是反射包下java.lang.reflect.Constructor类下的newInstance方法 User user2 = (User) constructor.newInstance("world"); System.out.println(user1.getName());//hello System.out.println(user2.getName());//world //2.无参构造器 Constructor
constructor1 = cc.getConstructor(); //无参构造不能够像1一样赋值 //User user3 = (User) constructor1.newInstance("熊本"); User user3 = (User) constructor1.newInstance(); user3.setName("熊本"); System.out.println(user3.getName());//熊本 //由无参构造器创建对象时,可不必获得构造器,直接由Class对象调用newInstance()方法。 Class
cc2 = User.class; User user4 = (User) cc2.newInstance(); user4.setName("同学"); System.out.println(user4.getName());//同学 //3.下面2个输出语句可看出cc保存类信息,输出的是“class + 类名”。cc.newInstance()是具体类的对象。 System.out.println(cc);//class com.newframe.controllers.api.User System.out.println(cc.newInstance());//com.newframe.controllers.api.User@3a03464 //4.AccessibleObject、Field类 //首先得到有参构造函数的信息,然后根据构造函数实例化一个对象。 //由getDeclaredField()函数得到类里面的私有成员变量,访问私有成员变量要用setAccessible()函数设置访问权限。 //Field类对象得到成员变量后还可以设置该变量的值,使用set()方法。 Constructor
constructor2 = cc.getConstructor(String.class); User user5 = (User) constructor2.newInstance("改变前:100"); Field field = cc.getDeclaredField("name"); field.setAccessible(true); field.set(user5,"改变后:50"); System.out.println(user5.getName());//改变后:50 //5.Method.invoke //首先根据获得的构造函数信息实例化一个对象 //然后由函数名获得类中的公有函数,getMethod("函数名") //invoke()方法执行由getMethod()获得的函数,这里获得的函数是getter() //对于获得的有参函数,invoke(对象)里只添加对象名。 Constructor
constructor3 = cc.getConstructor(String.class); User user6 = (User) constructor3.newInstance("你好世界"); //getName是User实体类中的方法 System.out.println(cc.getMethod("getName").invoke(user6));//你好世界 //对于获得到的无参函数,在调用getMethod()函数时,要在getMethod()中指定被获得函数的"函数名"和"参数类型" //并且在执行该函数(即调用invoke()函数时),要指定对象和参数类型的具体实例。 User user7 = (User) cc.newInstance(); Method method = cc.getMethod("setName", String.class); method.invoke(user7,"你好哇,这个世界"); System.out.println(user7.getName());//你好哇,这个世界 //6.Modifier类 //Class类中getModifiers()函数返回一个用于描述类,构造器,方法和域的修饰符的整形数值。、 //调用Modifier.toString()方法将整型数值转变成字符串,也是就我们熟悉的public,private,static,final等修饰符。 System.out.println(Modifier.toString(cc.getModifiers()));//无 System.out.println(Modifier.toString(constructor.getModifiers()));//public System.out.println(Modifier.toString(field.getModifiers()));//private System.out.println(Modifier.toString(method.getModifiers()));//public //同时,Modifier类还有一些判断修饰符是不是某一类型的方法。 System.out.println(Modifier.isPublic(cc.getModifiers())); System.out.println(Modifier.isPublic(constructor.getModifiers())); }}

3,数组的反射

public class TestReflectArray {    public static void main(String[] args) throws ClassNotFoundException {        //新建4个不同的数组        //一维数组        int[] a = new int[3];        int[] b = new int[4];        //二维数组        int[][] c = new int[3][4];        //String类型的数组        String[] d = new String[3];        //可以对比各个数组所属的类是否相同        System.out.println(a.getClass() == b.getClass());//true        //System.out.println(a.getClass() == c.getClass());不同类型的数组不同比较        System.out.println(a.length == c.length);//但是可以比较长度,true        System.out.println(a.getClass().getName());//[I        System.out.println(d.getClass().getName());//[Ljava.lang.String;        System.out.println(a.getClass().getSuperclass().getName());//java.lang.Object        //利用反射生成一个数组        int[] e = (int[]) Array.newInstance(int.class,3);        //0为数组索引下标,1为数字值        Array.set(e,0,1);        Array.set(e,1,2);        Array.set(e,2,3);        System.out.println(Array.get(e,0));        System.out.println(Array.get(e, 1));        System.out.println(Array.get(e, 2));        //利用反射获取数组类型常用的一些方式        Class
cc = String[].class; Class
cc1 = Class.forName("[I"); Class
cc2 = Class.forName("[Ljava.lang.String;"); System.out.println(cc); System.out.println(cc1); System.out.println(cc2); //通过已有的对象获取数组的类型 Class
cc3 = e.getClass(); System.out.println(cc3); //根据类型信息获取数组内成员的类型 Class
cc4 = cc3.getComponentType(); System.out.println(cc4);//int }}

 

转载于:https://www.cnblogs.com/cxsabc/p/10741999.html

你可能感兴趣的文章
小D课堂 - 零基础入门SpringBoot2.X到实战_汇总
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_2、SpringBoot2.x依赖环境和版本新特性说明...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_7、开发必备工具PostMan接口工具介绍和使用...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_4、快速创建SpringBoot应用之自动创建web应用...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_8、SpringBoot基础HTTP接口GET请求实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_6、SpringBoot2.xHTTP请求配置讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_10、常用json框架介绍和Jackson返回结果处理...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_9、SpringBoot基础HTTP其他提交方法请求实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_12、SpringBoot2.x文件上传实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_11、SpringBoot2.x目录文件结构讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第三节SpringBoot热部署devtool和配置文件自动注入实战_15、SpringBoot2.x配置文件讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_13、jar包方式运行web项目文件上传和访问...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_17、SpringBootTest单元测试实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第三节SpringBoot热部署devtool和配置文件自动注入实战_14、SpringBoot2.x使用Dev-tool热部署...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_19、SpringBoot个性化启动banner设置debug日志...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第三节SpringBoot热部署devtool和配置文件自动注入实战_16、注解配置文件自动映射到属性和实体类实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_20、SpringBoot2.x配置全局异常实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_18、SpringBoot测试进阶高级篇之MockMvc讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第5节 SpringBoot部署war项目到tomcat9和启动原理讲解_23、SpringBoot2.x启动原理概述...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_21、SpringBoot2.x配置全局异常返回自定义页面...
查看>>