在我们生活中,车上或者路上有时候会遇到一种很讨厌的人——“小偷”,趁我们不注意或者疏忽的时候拿走属于我们的东西。更有甚者,趁我们不在家的时候,手持一把万能钥匙,打开我们的房门,悠闲的查看房间的布置,翻找着他们需要的东西,惬意的时候也许会躺在客厅的沙发上,喝着冰箱里的饮料,俨然一副真正主人的样子。在JAVA中就有这样一个存在——“反射”,这是JDK提供的一把万能钥匙,任何人都可以使用它来获取本不应该属于自己的东西。

  在刚学习JAVA的时候,我们就知道,JAVA提供了private,protected,public,default四种修饰符,这四种修饰符象征着我们的使用权限。就好像我们的房子,房子是我们自己的,但是可以被子孙们继承,因此,房子可以被修饰为protected。房子里有的东西是我私人的,只属于我自己,谁都不能用,这可以被修饰为private。当然有的东西,亲戚朋友来了,都可以用,可以吃,那么可以被定义为default。看门外没有垃圾桶,个人本着爱护环境的初衷,放了一个垃圾桶在外面,谁都可以用,垃圾桶自己就可以被修饰为public。但是“小偷”就是没有这种限制,管你东西是不是私人的,他仗着手上的万能钥匙就是可以把这种访问权限糟蹋掉。尤其这把钥匙还是JDK出品的,很无奈!

  那下面就看看JDK提供的这把万能钥匙到底能干些什么吧。

  1、创建House类,代码如下:

package person.lb.reflect;/*** 房子* @author noboudns**/
public class House {//拥有者private String owner = "nobounds";//房间数private int roomNum = 3;//垃圾桶public String dustbin = "垃圾桶";public String getDustbin() {return dustbin;}private void turnOnTV() {System.out.println("打开电视……");}}

  2、创建KeyDemo 类,代码如下:

package person.lb.reflect;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;public class KeyDemo {public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, SecurityException, NoSuchFieldException {Class<?> clazz = Class.forName("person.lb.reflect.House");String className = clazz.getName();System.out.println("户主是:" + className);Field[] fields = clazz.getDeclaredFields();System.out.println("看看家里都有什么东西:");for(Field field : fields ) {System.out.println("类型:" + field.getType() + ",名称:" + field.getName() + ",使用权限:" + Modifier.toString(field.getModifiers()));}System.out.println("再看看家里有什么好玩的:");Method[] methods = clazz.getDeclaredMethods();for(Method method : methods) {System.out.println("名字:" + method.getName() + ",需要的东西:" + method.getParameterTypes().toString()+ ",得到什么:" + method.getReturnType().toString());System.out.println("用用看效果怎么样,嘿嘿!");//设置为可访问的method.setAccessible(true);method.invoke(clazz.newInstance());}System.out.println("心情不错,把房子据为己有吧!");House house = (House) clazz.newInstance();Field field = clazz.getDeclaredField("ownerName");field.setAccessible(true);field.set(house, "thief");System.out.println("现在房子的主人是:" + house.getOwnerName() );}
}

结果为:

户主是:person.lb.reflect.House
看看家里都有什么东西:
类型:class java.lang.String,名称:ownerName,使用权限:private
类型:int,名称:roomNum,使用权限:private
类型:class java.lang.String,名称:dustbin,使用权限:public
再看看家里有什么好玩的:
名字:getOwnerName,需要的东西:[Ljava.lang.Class;@3d4b7453,得到什么:class java.lang.String
用用看效果怎么样,嘿嘿!
名字:getDustbin,需要的东西:[Ljava.lang.Class;@1cc2ea3f,得到什么:class java.lang.String
用用看效果怎么样,嘿嘿!
名字:turnOnTV,需要的东西:[Ljava.lang.Class;@40a0dcd9,得到什么:void
用用看效果怎么样,嘿嘿!
打开电视……
心情不错,把房子据为己有吧!
现在房子的主人是:thief

  当然了,JDK中不止提供了这么多功能,如果有兴趣可以自己私下去查找相关资料,本文就不多说什么了。

  之前因为点儿事随笔写到了这里就发出去了,博友对内容有质疑,因此在这里稍微补充一下。

  我把反射冠名为“反射是小偷的万能钥匙”,虽然听着不好听,但是像这种有特殊能力的人或事物必然有它存在的道理以及特殊性,就像盗墓贼为了私利被称为“贼”,如果被国家收编,那么也能成为一个出色的考古学家。如果专门盗取别人私密数据以及搞破坏的出色黑客弃暗投明,那么很大概率上也能成为一个优秀的安全专家。小偷擅长偷盗,但是做起反偷盗的事情来也是一把好手。在JAVA中反射就被用在很多的框架以及产品中,例如Struts1/2,hibernate,Spring,Tomcat等使用反射不仅很大程度上提高了程序的灵活性,并对框架在加载以及管理Class的时候提供了很大的便利性,以及提供在程序运行时动态更改程序的行为的能力,进而提供丰富的功能,这也更方面了我们开发者。Spring的核心功能IOC和AOP的实现也都应用了JAVA提供的反射功能。那么下面就贴上两段Spring依靠注解注入依赖的源码见识一下。

  org.springframework.util.ReflectionUtils类(反射工具类):

……//如果类中的属性不是public修饰或者是final修饰并且属性是不可访问的,那么设置字段为可访问public static void makeAccessible(Field field) {if ((!Modifier.isPublic(field.getModifiers()) ||!Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { field.setAccessible(true);}}/*** Make the given method accessible, explicitly setting it accessible if* necessary. The {@code setAccessible(true)} method is only called* when actually necessary, to avoid unnecessary conflicts with a JVM* SecurityManager (if active).* @param method the method to make accessible* @see java.lang.reflect.Method#setAccessible*/public static void makeAccessible(Method method) {if ((!Modifier.isPublic(method.getModifiers()) ||!Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {method.setAccessible(true);}}/*** Make the given constructor accessible, explicitly setting it accessible* if necessary. The {@code setAccessible(true)} method is only called* when actually necessary, to avoid unnecessary conflicts with a JVM* SecurityManager (if active).* @param ctor the constructor to make accessible* @see java.lang.reflect.Constructor#setAccessible*/public static void makeAccessible(Constructor<?> ctor) {if ((!Modifier.isPublic(ctor.getModifiers()) ||!Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) {ctor.setAccessible(true);}}
……

  org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor类(@Autowired注解处理类):

……
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {private final boolean required;private volatile boolean cached = false;private volatile Object cachedFieldValue;public AutowiredFieldElement(Field field, boolean required) {super(field, null);this.required = required;}@Overrideprotected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {Field field = (Field) this.member;try {Object value;if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}else {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);TypeConverter typeConverter = beanFactory.getTypeConverter();value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);synchronized (this) {if (!this.cached) {if (value != null || this.required) {this.cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName)) {if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);}}}}else {this.cachedFieldValue = null;}this.cached = true;}}}if (value != null) {//设置字段访问权限为可访问
                    ReflectionUtils.makeAccessible(field);//对字段进行赋值
                    field.set(bean, value);}}catch (Throwable ex) {throw new BeanCreationException("Could not autowire field: " + field, ex);}}}
……

转载于:https://www.cnblogs.com/nobounds/p/5436791.html

我对java的理解(二)——反射是小偷的万能钥匙相关推荐

  1. java映射理解_Java反射的理解

    Java反射的理解 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的.于是我们直接对这个类进行实例化,之后使用这个 ...

  2. JAVA基础 (二)反射 深入解析反射机制

    在谈论到反射这个问题时,你是否有例如以下疑问? 不管是在.NET还是Java中反射的原理和机制是一样的,理解了一种还有一种就能够迎刃而解,想要理解反射首先须要了解底层的一些概念和执行.理解了反射有助于 ...

  3. Java学习之二-Java反射机制

    问题: 在运行时,对一个JAVA类,能否知道属性和方法:能否调用它的任意方法? 答案是可以的,JAVA提供一种反射机制可以实现. 目录 什么是JAVA的反射机制 JDK中提供的Reflection A ...

  4. java 反射应用_java反射(二)--反射应用案例

    一.反射实例化对象 经过一系列的分析之后发现虽然可以获取Class类的实例化对象,但是依然觉得这个对象的获取意义不是很大,因此可以通过以下几个案例去理解反射的核心意义 --反射实例化对象:获取Clas ...

  5. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  6. java不等长二维数组_Java中关于二维数组的理解与使用

    今天练习的时候遇到一个题目,题目需求是这样的: 需求说明: 根据3个班各5名学生某门课程的成绩,正确使用二维数组计算如图所示3个班各自的总成绩 分析: 要实现这个功能需要存储两个信息: 一个是班级信息 ...

  7. Java基础(二):集合、IO流(Zip压缩输入/输出流等)、File文件类、反射、枚举

    Java基础(一):编译和解释.数据类型.变量作用域.String常用方法.数组.面向对象.异常 Java基础(二):集合.IO流(Zip压缩输入/输出流等).File文件类.反射.枚举 Java异常 ...

  8. java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题

    原 java泛型(二).泛型的内部原理:类型擦除以及类型擦除带来的问题 2012年08月29日 23:44:10 Kilnn 阅读数:56717 版权声明:本文为博主原创文章,未经博主允许不得转载. ...

  9. Java:注解和反射

    (一)注解 1注解入门 Annotation是jdk1.5开始引入的新技术. Annotation的作用: (1)不是程序本身,可以对程序作出解释: (2)可以被其他程序(例如编译器)读取. Anno ...

最新文章

  1. Sublime-text
  2. PHP显示今天、今月、上月、今年的起点/终点时间戳
  3. php5.4 win10 mysql_win10本地搭建apache+php+mysql运行环境
  4. 简单的错觉画_错觉图片生成实验 - 正方形错觉
  5. mysql允许远程访问
  6. showModalDialog数据缓存问题
  7. 第三次学JAVA再学不好就吃翔(part42)--内部类概述
  8. Visible Lattice Points SPOJ - VLATTICE
  9. 百度云cdn设置州五年制大专_图说云原生:让云原生转型变得像种白菜一样简单...
  10. flex 颜色值uint与16进制的转换
  11. GitHub 的 12 个实用技巧,你 get 了几个?
  12. 测试电脑硬盘损坏的软件,硬盘检测工具哪个好 如何检测硬盘是否损坏【详细介绍】...
  13. 2021年10月份大厂网络工程师面试笔试题题【推荐收藏】
  14. 你知道哪几种MYSQL的连接查询
  15. 电子元器件之电容-2
  16. 一张图讲清楚产品架构,手把手教你画产品框架图
  17. 李宏毅svm_CAA | 【智能自动化学科前沿讲习班第1期】国立台湾大学(位于中国台北)李宏毅教授:Anime Face Generation...
  18. java retrofit_Android开发Retrofit2+Rxjava2+okHttp 网络框架封装
  19. 从前台获取数据,并导出PDF文件
  20. html5另存为本地文件,javascript实现文件另存为(web api)

热门文章

  1. python文本分类算法_python编写朴素贝叶斯用于文本分类
  2. ubuntu下常用的抓包软件_macOS下最常用也最好用的几款解压缩软件,你值得拥有...
  3. jedis java.lang.verifyerror_需要使用jfinal中的JedisPlugin的一些问题
  4. [Spring Boot核心功能]1. SpringApplication 启动引导类(2)
  5. [Ext JS 7]基于NPM的开发
  6. cta策略 有哪些_CTA量化策略学习笔记
  7. 并发执行linux命令结果混乱,Shell脚本--并发执行
  8. 基姆拉尔森计算公式(算任意日期是星期几)
  9. 解决 No module named ‘tensorflow.examples.tutorials‘
  10. 计算机三级之嵌入式系统学习笔记4