java 之 反射
2015-09-26 11:29
471 查看
反射 JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方 法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象 方法的功能称为java语言的反射机制。 动态获取类中信息,就是java反射。可以理解为对类的解剖。 如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。 所谓的框架就是对外提供一些接口,也就是功能扩展的标准,由实现类按照这个接口标准去实现。框 架内部如果需要操纵这些实现类的对象完成某些操作,那么只需要把这些实现类的全名(包名+类名)写 在某个配置文件中,框架代码只需要读取这个配置文件,就可以获取这个实现类的字节码文件,然后利 用反射技术创建这个实现类的对象并且调用相应的方法完成一些操作。 用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一 般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件 进行解剖,只要获取到该类的字节码文件对象即可。 —————————————————————————————————————————————————————————————————————————————————————— package demo.reflect; public class People { /** * 用于反射演示的类 */ private String name; private int age; public String address; public People() { } //修饰符不同 People(String name, int age) { this.name = name; this.age = age; } private People(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } public void show() { System.out.println("show~~"); } public void method(String s) { System.out.println("method" + s); } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", address=" + address + "]"; } } package demo.reflect; public class ReflectDemo { /** * 反射:通过class对象文件对象,去使用该文件中的成员变量,构造函数,成员方法 * * 首先应该获取class文件对象,也就是Class类的对象 * * Class类: 成员变量: Field 构造方法: Constructor 成员方法: Method * * 获取Class类的对象的方法 * 1 通过Object类的getClass()方法获取 * 2 数据类型的静态属性class * 3 Class类中的静态方法 * public static Class<T> forName(String className); * @throws ClassNotFoundException */ public static void main(String[] args) throws ClassNotFoundException { // getClass() People p1 = new People(); Class<? extends People> pc1 = p1.getClass();// 获取运行期间的类 People p2 = new People(); Class<? extends People> pc2 = p2.getClass(); System.out.println((p1 == p2) + "..." + (pc1 == pc2));//不同的类对象获取的Class文件对象是同一个 //类的静态属性 Class pc3 = People.class; System.out.println(pc3 == pc2); // Class类中的静态方法 forName() Class pc4 = Class.forName("demo.reflect.People"); System.out.println(pc3 == pc4); } } 输出: false...true true true —————————————————————————————————————————————————————————————————————————————————————— 通过反射,获取构造函数并创建实例 package demo.reflect; import java.lang.reflect.Constructor; public class Test { /** * @param args */ public static void main(String[] args) throws Exception { // 通过反射获取字节码文件对象 Class c = Class.forName("demo.reflect.People"); //获取构造函数,所有声明的构造函数 Constructor[] cons = c.getDeclaredConstructors(); for(Constructor con :cons) System.out.println(c.getPackage()+"..."+con); //通过构造函数创建新的实例 Constructor con = c.getDeclaredConstructor(); People p = (People)con.newInstance(); System.out.println(p); //带参的构造函数构造实例 Constructor con1 = c.getDeclaredConstructor(String.class,int.class); People p1 = (People)con1.newInstance("Lily",18); System.out.println(p1); Constructor con2 = c.getDeclaredConstructor(String.class,int.class,String.class); con2.setAccessible(true);//用私有的构造函数时,需要取消语言检查 People p2 = (People)con2.newInstance("Lily",18,"来宾"); System.out.println(p2); } } —————————————————————————————————————————————————————————————————————————————————————— 通过反射获取成员变量 package demo.reflect; import java.lang.reflect.Field; public class Test2 { public static void main(String[] args) throws Exception, SecurityException { //新建一个对象 People p = new People("Lucy",18); //获取字节码文件对象 Class pclass = p.getClass(); //通过字节码文件对象获取成员变量域Field对象 Field[] fs = pclass.getDeclaredFields(); for(Field f:fs) System.out.println(f); //获取单个变量的Field对象 Field nameField = pclass.getDeclaredField("name"); Field ageField = pclass.getDeclaredField("age"); //通过变量域对象,获取指定对象的对应变量值 nameField.setAccessible(true); System.out.println("name:"+nameField.get(p));//私有变量 ageField.setAccessible(true); System.out.println("age:"+(int)ageField.get(p)); } } —————————————————————————————————————————————————————————————————————————————————————— 练习: 将对象中字符串成员变量中的 'b' 全部换成 'a' package test.reflect; public class People { String name; String address; public People(String name, String address) { super(); this.name = name; this.address = address; } @Override public String toString() { return "People [name=" + name + ", address=" + address + "]"; } } package test.reflect; import java.lang.reflect.Field; public class Test { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { People p = new People("hbdbsf","bbbb"); System.out.println(p); chang(p); System.out.println(p); } public static void chang(Object obj) throws Exception { // 获取对象的字节码文件对象 Class c = obj.getClass(); // 获取成员变量的Field数组 Field[] fs = c.getDeclaredFields(); // 过滤出为String类型的Field // 获取对象相应Field的值,并进行替换字符 for(Field f:fs){ // System.out.println("field.getClass()"+f.getClass()); if(f.getType() == String.class){//字符串变量 String oldStr = (String)f.get(obj); String newStr = oldStr.replaceAll("b", "a"); f.set(obj, newStr); } } } } 输出结果: People [name=hbdbsf, address=bbbb] People [name=hadasf, address=aaaa]
相关文章推荐
- java 声明和动态创建数组
- java从命令行接收多个数字,求和之后输出结果
- java se 知识点(一)
- 一个JAVA代码
- java多线程环境下对变量的读写操作的原子性问题
- java代码
- Java代码
- Spring管理事务实现方式
- 我的java代码
- java 代码中实现 TextView的 DrawableTop属性
- OpenJDK 阅读源代码 Java 实现字节流输入类
- 《深入理解java虚拟机》之内存管理
- Java理论学时第一节。课后作业。
- java 抽象类和接口
- Java上机课后实践
- test7.22
- optimizer for eclipse--Eclipse优化,让你的Eclipse快来飞!
- 第一课
- Java学习之多态
- 设备MyEclipse6.5的maven