------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
< 今日心情 >放掉懒惰,再加上一份坚持
反射
映射就是将类中的各种成分映射成class类
类中的成分有:
Constructor 构造函数
Method 方法
Field 字段
import java.lang.*; import java.lang.reflect.*; import java.util.regex.*; class ReflectDemo { /* 映射一个People类,已知这个类 类中有含有两个成员变量 name-->姓名 email-->电子邮箱 这个类是单例模式 这个类的对象被使用时将不能再次被获取,直到使用者释放该对象的使用(调用该类的方法释放) 要求: 1.即使这个类的对象被使用,也可以获取 2.改变name的值和email的用户名,不改变email的域名 分析: 1.通过反射获取该类的类类型实例 2.通过实例获得构造方法的Constructor实例 3.改变并使构造方法的访问权限失效 4.创建People对象 5.通过该实例获取类的成员变量name和email的值 6.改变并使成员变量的访问权限失效 7.改变成员变量的值并赋值给对象 */ public static void main(String[] args) throws Exception { //对象已经被使用 People p=People.getPeople(); People p0=People.getPeople(); //三种方式获得people类的类实例 Class c1=p.getClass(); Class c2=People.class; Class c3=Class.forName("People"); //反射出该类的构造函数并创建对象 Constructor cr1=c1.getDeclaredConstructor(); cr1.setAccessible(true); People p1=cr1.newInstance(); //反射该类的成员变量,改变对象中成员变量的值 Field fName=c2.getDeclaredField("name"); fName.setAccessible(true); Field fEmail=c2.getDeclaredField("email"); fEmail.setAccessible(true); String newEmail=((String)fEmail.get(p1)).replaceAll(".+(@)","你猜$1"); //正则:String newEmail=Pattern.compile(".+(@)").matcher((String)fEmail.get(p1)).replaceFirst("你猜$1"); fEmail.set(p1,newEmail); fName.set(p1,"你猜"); //反射封装的show方法并调用 Method mShow=c1.getDeclaredMethod("show"); mShow.setAccessible(true); System.out.println("第一次使用,p:"+p); mShow.invoke(p); System.out.println("第二次使用,p0:"+p0); System.out.println("反射后使用,p1:"+p1); mShow.invoke(p1); /* 补充说明: get成分(成分名字,可变形参类型列表) get后加Declared可以获得被访问权限限制的成分,使用时要将其accessible设置为true invoke(对象名,可变实参列表) 前面的方法在类中属于静态成员时,对象名为null */ } } class People { private String email="bace@qq.com"; private String name="zhangsan"; //单例设计模式,私有一个本类对象 private static final People people=new People(); //标记该对象是否被使用或被释放 private static boolean flag=false; //私有构造方法,单例设计模式 private People() { } //获取该类的对象,在这个对象被使用并被释放以前不能再次获取 public static People getPeople() { if(flag) { System.out.println("该工作人员已经派出,请等待!"); return null; } else { flag=true; people.show(); return people; } } //封装的功能代码 private void show() { System.out.println("name:"+name+"---Email:"+email); System.out.println("为您服务!"); } public void release() { flag=true; } } method.invoke(Object obj,Object...args) 可以使用该方法调用反射获得类中的方法,obj为该类的一个实例 反射获得类中的方法是用数组做形参时,不能直接使用数组做参数传递。 原因: 在jdk1.4中,对invoke方法的定义为:invoke(Object obj,Object[] objs) 由向下兼容的原则,当把数组引用直接传递进来时,javajdk1.4的语法进行处理 即,把数组拆分成若干个参数来处理 解决办法: invoke(obj,new Object(){new XX[]{XX,XX..}}) invoke(obj,(Object)new XX[]{XX,XX..}) 数组的反射 数组也是一个类对象,通过class类的isArray方法判断反射的类是否是数组类, 借用Array工具类的get方法获取数组中的元素 如: public static void print(Object obj) { Class array=obj.getClass(); if(array.isArray()) for(int i=0;i