目录
一、什么是反射
二、为什么反射这项技术会出现
三、反射的原理
类加载机制与双亲委派模型
四、反射的优缺点
五、反射的用途
六、反射机制常用的类
七、反射的基本使用
1、获得class对象
2、判断一个对象是否为某个类的实例
3、创建实例:通过反射来生成对象主要有两种方法
4、通过反射获取构造方法并使用
例子
测试
5、获取成员变量并调用
6、获取成员方法并调用
7、反射入口main方法
8、利用反射创建数组
9、反射方法的其他使用--通过反射运行配置文件内容
10、反射方法的其他使用--通过反射越过泛型检查
本文参考自
大佬博客地址
推荐阅读
java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是jvm得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到jvm。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
下图是类的正常加载过程、反射原理与class对象:
class对象的由来是将.class文件读入内存,并为之创建一个class对象
javascript:void(0)
优点:
在运行时获得类的各种内容,进行反编译,对于java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
缺点:
反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
1、反编译:.class-->.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、开发时在使用ide,比如ecplise时,当在编辑器中输入一个对象或者类,并想调用它的属性和方法时,一按点号,编译器就会自动列出它的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(spring)都是配置化的(比如通过xml文件配置bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。
5、例如,在使用strut2框架的开发过程中,一般会在struts.xml里去配置action
比如我们请求login.action时,那么strutsprepareandexecutefilter就会去解析struts.xml文件,从action中查找出name为login的action,并根据class属性创建simpleloginaction实例,并用invoke方法来调用execute方法,这个过程离不开反射。配置文件与action建立了一种映射关系,当view层发出请求时,请求会被strutsprepareandexecutefilter拦截,然后strutsprepareandexecutefilter会去动态地创建action实例。
在比如,加载数据库驱动的,用到的也是反射。
java.lang.class;
java.lang.reflect.constructor;
java.lang.reflect.field;
java.lang.reflect.method;
java.lang.reflect.modifier;
主要有三种方法:
(1)object-->getclass
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过class类的静态方法:forname(string classname)(最常用,通过类的全类名获得类对象)
注意,在运行期间,一个类,只有一个class对象产生,所以打印结果都是true;
三种方式中,常用第三种,第一种对象都有了还要反射干什么,第二种需要导入类包,依赖太强,不导包就抛编译错误。一般都使用第三种,一个字符串可以传入也可以写在配置文件中等多种方法。
一般在需要判断某个对象是否为某个类的实例时,可以使用instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中class对象的isinstance()方法来判断时候为某个类的实例,这是一个native方法。
使用class对象的newinstance()方法来创建class对象对应类的实例。
先通过class对象获取指定的constructor对象,再调用constructor对象的newinstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例。
批量获取的方法:
单个获取的方法,并调用:
调用构造方法:
<code>constructor-->newinstance(object... initargs)</code>
<code>newinstance</code>是<code>constructor</code>类的方法(管理构造函数的类)
api的解释为:<code>newinstance(object... initargs)</code> ,使用此<code>constructor</code>对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是t类型,所以newinstance是创建了一个构造方法的声明类的新实例对象,并为之调用。
student类:共六个构造方法
student类
测试
控制台结果
测试类
控制台输出
数组在java里是比较特殊的一种类型,它可以赋值给一个object reference。
配置文件以<code>txt文件</code>为例子:
需求
之后升级这个系统时,不要student类,而需要新写一个student2的类时,这时只需要更改pro.txt的文件的类名就可以了。客户端代码就一点不用改动。
配置文件更改为:
泛型用在编译期,编译过后泛型擦除(泛型全部消失掉,都是object),所以是可以通过反射越过泛型检查的