Java编程中,有个有意思的东西,叫做反射,这个名字和真正的用途感觉没啥关系,不过也别埋怨翻译的水平,因为英文原文就比较奇怪。英文为Reflection,词霸翻译如下:
这个干啥用的呢?待我慢慢道来。
一般类有些属性和方法是外部不允许访问的,但是某些情况,我们却希望去修改某个类的私有属性值或者调用某个私有方法。正常途径不行,但是通过反射却可以。这也是Java动态性的一个体现,可以看看下面具体的代码:
代码简析:
- 第11到21行,定义了一个User类,里面定义了一个age属性,访问权限定义为private私有,外部不可访问;定义了 setAge方法,也是私有的;getAge方法,这个public可公开访问的。
- 第4行,main方法,为程序执行入口。
- 第5行,定义了User变量并赋值。
- 第6和7行,可以看到红色部分,表示代码报错。因为age属性和setAge方法都是私有的,不可以直接访问。不过通过反射却可以访问。代码如下:
代码简析:
- 第9行,通过“user.getClass().getDeclaredMethod”可以获取User类中指定的方法,注意后面要带上参数名称和类型(本例中类型是Integer)。
- 第10行,调用setAccessible(true),让这个方法变成外部可以调用。
- 第11行,调用method.invoke(user, 22)来执行方法,达成最终目标。
上面是调用的私有方法,也可以直接修改私有属性,代码如下:
- 第9行,调用user.getClass().getDeclaredField获取User中指定属性。
- 第10行,调用setAccessible(true),让这个属性变成外部可以调用。
- 第11行,调用field.set(user,22) 进行属性值修改。
回味一下,是不是超级强大,看不到的东西都看到了,改不了的东西都改了,有点黑客的味道了。
好吧,还是继续吧。反射还有一个好用的功能:根据类名新建对象。
通常,我们都是直接拿到类,用new关键字来创建出对象,但是如果通过反射创建对象,就只需要一个类名字符串。
常规创建:
User user = new User();
反射创建:
User user = (User)Class.forName("com.shidaimanong.demo.reflect.User").newInstance();
是不是觉得上面反射的做法简直是脱裤子放屁,多此一举,非也,这种方式有很大的用处。著名的开源组件Spring,它的IOC容器核心就是通过xml配置,依靠反射来生成并管理对象的。当然,平常我们比较少用到反射,能使用到反射的时候,你就肯定不简单了。
声明: 因本文前期在头条发布并且当时名称为“十代码农”,所以截图带有十代码农的水印。