Reflect----Java反射基础总结
2015-09-23 20:23
381 查看
------- android培训、java培训、期待与您交流! ----------
Reflect—————java反射基础
1定义:java程序运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法(包括私有),对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态类型信息及动态调用对象方法的功能叫做java反射机制;
2理解:
1以前都是在编译期间玩类和对象,现在转到运行期间来玩类和对象;因为java程序在运行时由类加载器将.class文件 加载到内存中(方法区),并为其创建与之对应的Class对象,而我们要通过这个Class对象来使用反射功能;
2Class对象(字节码文件对象):
2.1他将类型信息用自己的数据所描述,即,这个对象也有构造其,成员变量和成员方法,而且这些分别又被封装成为对象,这些对象对应的就是被加载类的字段,构造器,方法;
2.2从上面的分析来看,我们操作字节码文件对象就可以获取到一个类的所有信息,并可以用这些功能来创建对象,改变属性,所以操作步骤为:
2.21:获取字节码文件对象
2.22:用字节码文件对象获取的被加载类字段,构造器,方法的封装类型(Constructor,Filed,Method)
2.23:再通过以上三个类来判断,操作这个被加载类
3产生Class对象的时机,即加载器合适加载这个类:
1,当使用new关键字创建对象时 2调用类中的静态属性,或者为其赋值(final)以及调用静态方法
3,使用反射创建某个类或借口
4初始化某个类的子类
5,使用java.exw来运行某个主类(tomcat,批量处理文件)
3.2获得一个类的字节码文件对象的方式:
1类型.class; 2 Object.getClass(); 3Class.forName("全路径");
4类加载的组成以及工作原理:
4.1根类加载器 --Bootstarp classloader ---负责加载jdk核心文类 -----> jdk/jre/lib/rt.jar
4.2扩展类加载器 --Extension classloader ---负责加载jdk核心文类 -----> jdl/jre/lib.ext
4.3系统类加载器 --System classloader ---负责加载jdk核心文类 -----> java 命令指定的.class文件(我们自定义的)
4.4执行步骤:加载(创建Class对象),连接(验证,准备,解析一些准备动作),初始化
5代码演示
5.3运行结果
Room[深圳56.0]
public void com.itheima.reflect.Room.setRoomName(java.lang.String)
你好,黑马
6练习:向ArrayList<Integer>添加一个String对象;
运行结果:
[哈哈,我是字符串]
总结:
1形象理解,如果说在编译阶段,基类是Object的话,那么在运行阶段,基类就是Class字节码文件对象;
2反射带来的好处我还么有再身一步的去学习,但是有用过spring这个框架,工厂设计模式,反射的功能实现,我们只需要操作配置文件就可以了;还需要好好努力学习啊
Reflect—————java反射基础
1定义:java程序运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法(包括私有),对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态类型信息及动态调用对象方法的功能叫做java反射机制;
2理解:
1以前都是在编译期间玩类和对象,现在转到运行期间来玩类和对象;因为java程序在运行时由类加载器将.class文件 加载到内存中(方法区),并为其创建与之对应的Class对象,而我们要通过这个Class对象来使用反射功能;
2Class对象(字节码文件对象):
2.1他将类型信息用自己的数据所描述,即,这个对象也有构造其,成员变量和成员方法,而且这些分别又被封装成为对象,这些对象对应的就是被加载类的字段,构造器,方法;
2.2从上面的分析来看,我们操作字节码文件对象就可以获取到一个类的所有信息,并可以用这些功能来创建对象,改变属性,所以操作步骤为:
2.21:获取字节码文件对象
2.22:用字节码文件对象获取的被加载类字段,构造器,方法的封装类型(Constructor,Filed,Method)
2.23:再通过以上三个类来判断,操作这个被加载类
3产生Class对象的时机,即加载器合适加载这个类:
1,当使用new关键字创建对象时 2调用类中的静态属性,或者为其赋值(final)以及调用静态方法
3,使用反射创建某个类或借口
4初始化某个类的子类
5,使用java.exw来运行某个主类(tomcat,批量处理文件)
3.2获得一个类的字节码文件对象的方式:
1类型.class; 2 Object.getClass(); 3Class.forName("全路径");
4类加载的组成以及工作原理:
4.1根类加载器 --Bootstarp classloader ---负责加载jdk核心文类 -----> jdk/jre/lib/rt.jar
4.2扩展类加载器 --Extension classloader ---负责加载jdk核心文类 -----> jdl/jre/lib.ext
4.3系统类加载器 --System classloader ---负责加载jdk核心文类 -----> java 命令指定的.class文件(我们自定义的)
4.4执行步骤:加载(创建Class对象),连接(验证,准备,解析一些准备动作),初始化
5代码演示
package com.itheima.reflect; /** * 被反射操作的类 */ public class Room { private String roomName; private float price; private int roomNum; private boolean isUse; public Room() { } private Room(String roomName, float price) { this.roomName = roomName; this.price = price; } @Override public String toString() { return "Room["+roomName+price+"]"; } //这个教室有多少个人 private void printHotWater(int x){ System.out.println("这个教室有"+x+"个人"); } //getter and setter 为了不占屏幕,此处省略了代码 }
5.2
package com.itheima.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectBase { public static void main(String[] args) throws Exception { //被操作的字节码对象 Class<?> clazz = Class.forName("com.itheima.reflect.Room"); /** * 构造器 * */ // 获得指定参数列表的构造器 Constructor<?> con = clazz.getDeclaredConstructor(String.class,float.class); //获得访问权限,通过私有构造方法构造出一个Room对象 con.setAccessible(true); Object room= con.newInstance("深圳",56f); System.out.println(room); /** * 方法 * */ //调用set方法,改变一个字段的值,param1:方法名,param2:这个方法指定的参数列表的参数类型 Method method=clazz.getDeclaredMethod("setRoomName", String.class); method.invoke(room, "你好,黑马"); System.out.println(method.toGenericString()); /** * 字段 * */ //再次反射得到这个改变字段的值,并检验 Field changeFiled=clazz.getDeclaredField("roomName"); changeFiled.setAccessible(true); //反向读取,反向理解,这个对象的这个方法 Object value=changeFiled.get(room); //校验 System.out.println(value); } }
5.3运行结果
Room[深圳56.0]
public void com.itheima.reflect.Room.setRoomName(java.lang.String)
你好,黑马
6练习:向ArrayList<Integer>添加一个String对象;
<span style="font-family:SimHei;font-size:12px;">/** * 分析:1泛型只是给编译器使用的一个安全机制,实际源代码中添加的是Object类型的元素 * 要想添加泛型外的元素必须考虑从运行期下手 * 2通过反射获取到ArrayList添加元素的方法,并执行那个方法 */ public class ArrayListTest { public static void main(String[] args) throws Exception { ArrayList<Integer> intArr=new ArrayList<>(); //获取字节码文件对象 Class clazz=intArr.getClass(); //获取添加元素的方法 Method m=clazz.getMethod("add",Object.class); //操作add方法,放入值 m.invoke(intArr, "哈哈,我是字符串"); //校验 System.out.println(intArr.toString()); } }</span>
运行结果:
[哈哈,我是字符串]
总结:
1形象理解,如果说在编译阶段,基类是Object的话,那么在运行阶段,基类就是Class字节码文件对象;
2反射带来的好处我还么有再身一步的去学习,但是有用过spring这个框架,工厂设计模式,反射的功能实现,我们只需要操作配置文件就可以了;还需要好好努力学习啊
相关文章推荐
- java学习之IO其他流
- JAVA 实现斗地主分牌
- JAVA中数据类型划分应该注意的事项
- JAVA Calendar实现出生天数计算
- Java 猜数字小游戏
- Java内存管理原理及内存区域详解
- java双重检测锁
- 杭电ACM2061java做法(PE)
- eclipse启动不了
- ListView在removeFooterView时报java.lang.ClassCastException错问题
- Java 设计模式(2)工厂模式
- Unable to locate Spring NamespaceHandler for XML schema namespace
- JAVA WEB 总结 Servlet篇
- Myeclipse_Pro_GA_2014的服务器视图(Servers)中的MyEclipse Derby选项如何去掉
- Spring 漏洞分析
- myeclipse 导入项目 输入此项目名不能运行问题
- java 安全了解
- kMeans算法JAVA实现
- ognl+struts2
- Java之旅Struts系列(3)——Struts2(前奏篇)