今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉。

所谓的反射,就是在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以-----很强大。

    想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

    获取字节码文件对象的三种方式。

       1、Class clazz1 = Class.forName("全限定类名");  //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。

       2、Class clazz2 = Person.class;    //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。

       3、Person p = new Preson();

Class clazz3 = p.getClass();    //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段 

  有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。下面介绍Class类的功能

反射机制能够获得的信息:

1.1通过字节码对象创建实例对象:

//如果user类还没有加载,那么可以在源文件阶段获取其字节码文件对象

Class clazz1 = Class.formName("Reflect.User");

//创建User实例,这里通过User的无参构造方法来创建对象

User user = (User)clazz1.newInstance();

//然后通过user对象就可以获取我们想要的信息

1.2获取指定构造器方法,constructor没有无参构造方法:

//获取字节码文件

Class clazz1 = Class.forName("Reflect.User");

//先获取有参构造器,parameterType:表示参数列表,有多少就要写多少,如果不写,默认调用无参构造方法

Construnctor con = clazz1.getConstructor(int.class,String.Class);

//通过构造器来实例化对象,将实际的参数传进去

User user = (User)con.newInstance(12,"小明");

总结上面创建实例对象:该类无参的构造方法来是使用该Class类的newInstance()方法来创建对象的, 如果一个类没有无参的构造函数, 就不能这样创建了。

这时候可以使用getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象获取全部构造方法。

Class clazz1 = Class.forName("Reflect.User");

//获取所有的构造方法

Constructor[] con = clazz1.getConstructors();

//for循环遍历

for(int i=0;i<con.length;i++){

//获取每个构造函数中的参数类型字节码对象

Class[] parameterTypes = con[i].getParameterTypes();

syso("第"+i+"个构造函数");

for(int j =0;j<paraparameterTypes.length;j++){

//获取构造函数中的参数类型

syso(paraparameterTypes[j].getName()+",");

}

}

1.3获取成员变量并使用---Filed对象

获取指定成员变量

Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以使用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值。

1.4获得方法并使用 Method

Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法,如果为私有方法,则需要打开一个权限。setAccessible(true);用invoke(Object, Object...)可以调用该方法,跟上面同理,也能一次性获得所有的方法:

1.5、获得该类的所有接口

   Class[] getInterfaces():确定此对象所表示的类或接口实现的接口

   返回值:接口的字节码文件对象的数组

1.6、获取指定资源的输入流

   InputStream getResourceAsStream(String name)  

   return:一个 InputStream 对象;如果找不到带有该名称的资源,则返回 null

   参数:所需资源的名称,如果以"/"开始,则绝对资源名为"/"后面的一部分。

上面讲了一些反射的概念和方法,但是在我们开发中,经常会出现这样的情况,就是随着业务逻辑的不断增多,每写一个功能时,就需要写一个对应的servlet,最后就会导致Servlet异常的臃肿。下面来说说如何在servlet中使用反射对其进行优化:

每次从页面传过来一个参数,method="xxx"; 然后编写一个Servlet,获得其参数method的值,进行判断,如果是add,则调用add方法,如果是delete,则调用delete方法,这样就可以写在一个servlet中实现所有的功能了。

编写一个BaseServlet继承HttpServlet,这是一个通用的BaseServlet,这里需要我们明白servlet的生命周期,也就是service方法,因为是servlet,所以在访问的时候,会经过service方法,而子类MyServlet001中并没有,所以就到父类BaseServlet中找,发现有,然后获取参数即知道了需要调用什么方法,因为方法的编写都在子类中,所以通过反射,获取到子类中对应的方法并运行,其中需要注意的是this这个参数在BaseServlet中的用法,需要理解它,才能理解我们这个程序。

编写具体实现的方法servlet类。MySerlvet001 extends BaseServlet

formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化相关推荐

  1. java中的io复用_从 Java 中的零拷贝到五种IO模型

    在之前的文章中,我们聊过了 Java 中的零拷贝,零拷贝就是指数据不会在内核空间和用户空间之间相互拷贝.这样就减少了内核态与用户态的切换,自然就很高效. 拷贝文件只是 IO 操作中一个特殊的情况,大多 ...

  2. java 异常对象_在java中的异常处理中的异常对象是什么

    展开全部 Exception类以及他的子类 的一个实例对象 比如32313133353236313431303231363533e58685e5aeb931333264633563 常见异常 1. j ...

  3. java类怎么删除对象_在java中删除一个对象?

    在java中删除一个对象? 我想删除一个我创build的对象(跟随着你的一个椭圆),但是我怎么做呢? delete follower1; 没有工作. 编辑: 好吧,我会给更多的上下文. 我正在制作一个 ...

  4. java释放对象_在Java中释放Semaphore对象的正确方法是什么...

    信号量没有所有权概念.许可证不是真实的东西,只是信号量保持的计数.所以问题是,方法执行后计数正确吗? 如果您被打扰了,您会留下一个或两个可用许可证吗? api文档中Oracle网站上的信号量示例没有f ...

  5. java如果把字符串转成对象_为什么Java中的字符串对象是不可变的,有什么好处?...

    专注于Java领域优质技术号,欢迎关注 原创: 阿杜的世界 阅读本文大概需要 4分钟. 所谓不可变对象,是指一个对象在创建后,它的内部状态不会被改变的对象.这意味着当我们将一个不可变对象的引用赋值给某 ...

  6. java 堆栈 对象_在Java中,哪些对象放在堆栈上,哪些放在堆上?

    对于 Java函数中的语句: Xxx xxx = new Xxx() { public Abc abc(final Writer out) { return new SomeFunction(out) ...

  7. java中的方法求和_在Java中模拟求和类型的巧妙解决方法

    java中的方法求和 在继续阅读实际文章之前,我想感谢令人敬畏的Javaslang库的作者Daniel Dietrich ,他在我面前有了这个主意: @lukaseder尝试使用静态方法<T,T ...

  8. java中字符流 字节流_理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个"流动的方向",通常可 ...

  9. 在java中如何输入角度_在Java中获取角度的反余弦

    为了获得Java中给定值的反余弦,我们使用java.lang.Math.acos()方法.该acos()方法接受需要计算角度的双精度值.返回的角度范围在0到pi之间.如果参数为NaN或大于1或小于-1 ...

最新文章

  1. mvc存储Cookie和读取Cookie方法
  2. 读书笔记 — Java高并发程序设计 — 第三章 — 锁
  3. 一阶差分单位根检验_计量经济学第11讲(时间序列计量经济学模型:平稳性及其检验)...
  4. 江苏实时分析评价系统项目总结报告
  5. Linux : ext3_free_blocks: Freeing blocks not in datazone
  6. 机器学习/深度学习常用库的配置及其适用的算法总结
  7. 时序报告要看哪些指标
  8. 2021-11-17每日刷题打卡
  9. 网络写作一年稿酬最高可达150万元
  10. D2D加载图片资源(2)
  11. excel处置4000行数据卡_数十万数据Excel数据不好处理怎么办?几行Python搞定
  12. 国产操作系统Office哪个好用?6款工具推荐!
  13. vue实现中根据字母或者中文进行排序
  14. C++ 强制类型转换:static_cast、dynamic_cast、const_cast 和 reinterpret_cast
  15. UFUNufun币ufun优趣集团
  16. 如何下载网易云音乐APP里的MV和短视频?
  17. 充气娃娃?Python告诉你到底有多爽......
  18. 微波课设 基于pyqt5+pyqtgraph的Smith圆图GUI程序设计
  19. 平淡生活:戴戒指的学问
  20. 537 复数乘法(模拟)

热门文章

  1. 简谈Java的join()方法(转)
  2. 《The Pursuit of Happyness / 当幸福来敲门》(2006)
  3. Windows Server 2003 SP2中文版开放下载
  4. winscp怎么更改linux权限,Linux下,WinSCP普通用户登录sftp后切换到root权限 教程
  5. mysql有没有mssql执行计划_MSSQL优化执行计划
  6. python创建一个有序链表_Python实现合并两个有序链表的方法示例
  7. Mac/Linux使用fcrackzip
  8. Mac安装iproute2/dig/traceroute
  9. AudioUnitRender -10876
  10. Windows中的磁盘分区、MBR、GPT