反射详解
来源:互联网 发布:畅捷通软件介绍 编辑:程序博客网 时间:2024/06/06 00:20
反射技术==>动态加载一个指定的类.获得该类的字节码文件对象-->获得该类中所有的内容.-->对类进行解剖
1.类的初始化:
类的初始化:就是类的加载,将类从硬盘放到内存中.
时机:什么时候使用到这个类,加载器就会将该类加载到内存中.
1.创建类的实例
2.类的静态变量,或者为静态变量赋值
3.类的静态方法
4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5.初始化某个类的子类
6.直接使用java.exe命令来运行某个主类
2.类的加载器: -->(原理:就是按照一定的格式将硬盘上的文件读入到内存中)
负责将.class文件加载到内在中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行
Bootstrap ClassLoader根类加载器.==>也叫引导类加载器
加载核心类库...System,String...主要是\lib\rt.jar
Extension ClassLoader扩展类加载器==>
扩展类加载器,目前只要加载src\lib\ext文件夹.
System ClassLoader系统类加载器
主要是加载用户自定义的,或者用户导入的第三方jar包.
3.如何获得Class文件对象,字节码文件对象.
1.通过该类的对象,直接获得:
Class clazz = obj.getClass(); ==>必须创建该类的对象.
2.通过类中的静态方法或者静态的成员变量.静态的属性class.
3.使用Class类中的方法.
Class clazz = Class.forName(classname);
注意:第三种和前两种的区别前两种你必须明确Person类型.后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了
4. 反射的使用步骤:
1.获得指定类的Class文件对象,(获得字节码文件对象)
2.实例化对象,获得类的属性,方法或构造方法.
3.访问属性,方法,调用构造方法创建对象.
5.反射的用法:
1.获得Class文件的对象.
★★Class clazz = Class.forName(classname);用于类加载.
classname需要全名..eg:com.mysql.jdbc.Driver -->不可以带class后缀.
Class clazz = Person.class 类名获取.
Class clazz = p.getClass() 类对象直接获取.
快速创建对象:
1.类需要有空参构造
2.该空参构造权限需要是public
Object obj =clazz.newInstance();
直接通过clazz文件对象创建对象,底层就是使用类的空参获得的实例.
2.反射类的构造方法:
Constructor con =clazz.getConstructor(Class<?>... params );//只能获得public修饰的.
获得任意一个公有的指定参数列表的构造,如果不指定参数,获得的就是空参构造.
Constructor con =clazz.getDeclareConstructor(Class<?>... params );//可以获得私有的构造
获得任意一个(包括私有的)指定参数列表的构造,如果不指定参数,获得的就是空参构造.
Constructor[] cons= clazz.getDeclareConstructors(Class<?>... params );//可以获得私有的构造
获得该类中的所有的(包括私有的)构造方法.
通过对象的构造器,获得该类的实例对象:
Object obj =con.newInstance(Object ... params); //参数传递,是根据使用的构造方法的参数列表来确定.
3.反射类的属性.
Field field = clazz.getField(String name);
//获得指定名称的属性字段对象.只能是public修饰的
Field[] fields = clazz.getDeclareFields();//无需名称.
获得该类中以及父类或者接口中继承的所有字段,包括私有的.
field.setAccessable(true);//取消访问权限.
field.set(Object obj,Object value); //设置obj对象的该field字段的值为value.
4.反射类的方法.
Method[] methods = clazz.getDeclareMethods();
//返获得该类中所有的方法,包括私有的.
返回 Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有的方法,
包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法.
Method method = clazz.getDeclareMethod(Stringmethodname,Class<?>...params);
获得一个指定名称的方法.参数为该方法的参数类型的class文件.
method.setAccessable(true);
method.invoke(Object obj,params);
-->调用obj对象中的method方法.传入的参数为params.(需要和前面获得的方法的参数列表相同.)
反射的应用:
1.泛型擦除.
定义泛型限制的集合,向其中存入非泛型限定的数据类型.
*分析:
* 1.要想在一个指定泛型(Integer类型)的list集合中存入一个String类型的对象,就需要使用到反射技术.
* 2.考虑到list添加元素的方法是add.因此,准备使用add方法进行反射添加.
ArrayList<Integer>list=newArrayList<Integer>();
//第一步,获得该对象的字节码文件.
Classc=list.getClass();
//第一个参数,是方法名.第二个参数是参数类型的字节码文件.
Methodmethod=c.getDeclaredMethod("add",Object.class);//获得该类的add方法
method.setAccessible(true);//取消访问限制
method.invoke(list,"我是字符串,就要加进来,气死你!");
使用代码进行测试:
/** * 自定义一个测试类 * @author myth * */public class User {//私有属性.private String name;private String sex;//一个方法public void say(String exten) {System.out.println("你好:"+name+"附加字符为 :"+exten);}//构造默认为无参的.public User(){} //可以不声明的.}
用于测试用的类
反射的代码:
/** * 这个测试,是为了说明,有了反射,有了对应类的全路径. * 我们可以获得该对象的所有的字段,方法.以及构造.(包括私有的.) * 并且,我们可以暴力反射,即使该类没有指定对应的get/set方法,我们也可以去设置值. * @author myth * */public class ProxyTest {@Testpublic void test() throws Exception {//获得该类的字节码文件对象.Class clazz = Class.forName("com.myth.proxy.User");//通过该类的空参构造一个对象.没有空参,这个方法就会报错.User user = (User) clazz.newInstance();//获得所有的属性字段.包括私有的.Field[] declaredFields = clazz.getDeclaredFields();//遍历所有字段.for (Field field : declaredFields) {//因为想对name字段赋值.所以对字段进行判断.if ("name".equals(field.getName())) {//暴力反射,否则无法设置参数.因为该字段声明是私有的.field.setAccessible(true); field.set(user, "二哈"); //设置对应字段的值.//该语句类似于 user.setName("二哈");但是我们并没有提供get/set方法的.}}//获得对应方法名称的方法.(方法也是一个Method类的对象.)
//通过匹配方法名,得到一个唯一方法对象.Method method = clazz.getDeclaredMethod("say",String.class);//System.out.println(method);//public void com.myth.proxy.User.say(java.lang.String)//System.out.println(method.getName()); //saymethod.invoke(user, "哈哈");}}
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解
- 反射详解!
- 反射详解
- java反射机制详解!
- java 反射机制详解
- 消息反射详解
- 详解C#中的反射
- JAVA反射详解
- C#反射实例详解
- JAVA反射机制详解
- 安装activex控件(64位机器MSComm32)
- 记录AWS使用产生的EBS费用
- spark源码之RDD(1)partition、dependence、persist
- 类加载机制及类加载器加载Class流程
- 在Ubuntu上下载、编译和安装Android最新源代码
- 反射详解
- Android Bitmap处理
- miniui表格分页(mybatis)
- C++fstream,ifstream和outstream读取文件最后一行注意
- POJ 1273 Drainage Ditches 网络流 ISAP
- C++ 带默认形参值的函数
- CPU中的八个通用寄存器
- Android系统级开发进程清理功能的一些记录和发现
- Ubuntu 16.04 安装Opencv3.1.0 (选装opencv_contrib模块)