一、反射Class 基本分析
反射的基石: Class 字节码 //得到这个类的字节码的实例对象3种 类名.class 如,System.class; 对象.class 如p1.getClass(); Class.for("java.lang.String"); //返回字节码
有9个预定义的Class实例对象 8个基本类型对应的,加1个void 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象
。 Class cls1 = void.class;
package ZHANG.Reflect; public class TestReflect { public static void main(String[] args) throws Exception { String str1 = "abc"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); System.out.println(cls1 == cls2); System.out.println(cls2 == cls3); System.out.println(cls1.isPrimitive());//是否是一个基本类型的字节码 //flase System.out.println(int.class.isPrimitive()); //true System.out.println(int.class == Integer.class); //false System.out.println(int.class == Integer.TYPE); //基本类型可以写成这样 true System.out.println(int[].class.isPrimitive()); //false System.out.println(int[].class.isArray()); //数组的Class实例对象 true } }
二、反射加强
反射就是把Java类中的各种成分映射成相应的java类。 ---Class对象,类的组成部分: 成员变量,方法,构造方法,包等等信息。 ---来获取其中的变量,方法,构造方法,修饰符,包等信息,用相应类的实例对象来表示, 它们是File、Method、Constructor、Package等等
class --->constructor --->new Object
Constructor类 ---得到某个类所有的构造方法 Constructor[] constructor = Class.forName("java.lang.Sting").getConstructor(); ----得到类中某一个构造方法 //获得方法时要用到类型 Constructor con1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class); ---创造实例对象 //获得调用方法时候用到上面相同类型 1. 通常方式 String str = new String(new StringBuffer("abc")); 2.反射方式 String str = (String)constructor.newInstance(new StringBuffer("abc")); ----Class.newInstance()方法 Sting obj = (String)Class.forName("java.lang.String").newInstance(); //该方法内部得到构造方法,然后用该构造方法创造实例对象。 //用到了缓存机制来保存默认构造方法的实例对象
//new String(StringBuffer.class) 用构造方法做同样功能 Constructor constructor1 = String.class.getConstructor(StringBuffer.class); String str = (String) constructor1.newInstance(new StringBuffer("abc")); //这里注意需要传递同样类型的对象new StringBuffer System.out.println(str.charAt(2)); //c
成员变量的反射---Field类
ReflectPoint.java
package ZHANG.Reflect; public class ReflectPoint { private int x; public int y; public String str1 = "ball"; public String str2 = "basketball"; public String str3 = "itcast"; public ReflectPoint(int x, int y) { this.x = x; this.y = y; } @Override public String toString() { return str1+":"+str2+":"+str3; } }
//获得其值方法
ReflectPoint pt1 = new ReflectPoint(2,5); Field fieldY = pt1.getClass().getField("y"); //y是public //fieldY不是对象身上的变量,而是类上的,用它去取变量上的值get() System.out.println(fieldY.get(pt1)); Field fieldX = pt1.getClass().getDeclaredField("x");//x是private,该方法不管是否私有 fieldX.setAccessible(true); //获得其值X,需要设置可见 System.out.println(fieldX.get(pt1));
//把对象上所有的String成员变量中的"b"换成"a"
main方法中
changeStringValue(pt1); System.out.println(pt1);
替换方法
private static void changeStringValue(Object obj) throws Exception { Field[] fields = obj.getClass().getFields(); for(Field field : fields){ //字节码用"=="比 if(field.getType() == String.class){ String oldValue = (String) field.get(obj); String newValue = oldValue.replace("b", "a"); field.set(obj, newValue); } } }
Method类 ---代表某个类上的一个成员方法
----得到类中的某一个方法 Method charAt = Class.forName("java.lang.String").getMethod(charAt,int.class); ---调用方法 1. 通常方式 System.out.println(str.charAt(1)); 2.反射方式 System.out.println(charAt.invoke(str,1)); //如果传递给Method对象的invoke()方法的一个参数为null,,,说明该Method对象对应的是一个静态方法
//new Object[]{new String("abc"),1}; //得到成员方法 str.charAt(1) Method methodCharAt = String.class.getMethod("charAt", int.class); //获得String上的charAt方法,返回值是int类型 methodCharAt.invoke(str, 1);//调用str对象上charAt的时候有传一个参数//这个方法是str对象上 methodCharAt.invoke(str, new Object[]{2}); //按照JDK1.4语法调用
=================用反射方式执行某个类中的main方法
在类中再增加一个类
class TestArgments{ public static void main(String[] args) { for(String arg :args) System.out.println(arg); } }
调用代码如下:
//平时调用方法 // TestArgments.main(new String[]{"234","432","hha"}); //用反射调用 String startmain = args[0]; //main中传入ZHANG.Reflect.TestArgments Method mainMethod = Class.forName(startmain).getMethod("main", String[].class); // 2种解决方案mainMethod.invoke(null, new Object[]{new String[]{"232","abc","432"}});//需要装载Object,每个数组都是Ojbcet mainMethod.invoke(null, (Object)new String[]{"232","abc","432"}); }
======数组的反射 Array工具类用于完成对数组的反射操作 //不能得到数组中的整个元素类型 ,,只能得到某一个元素类型 对数组进行反射
int[] a1 = new int[]{1,3,4}; int[] a2 = new int[4]; int[][] a3 = new int[2][3]; String[] a4 = new String[]{"a","b","c","d"}; System.out.println(a1.getClass() == a2.getClass()); System.out.println(a1.getClass() == a3.getClass()); System.out.println(a1.getClass() == a4.getClass()); System.out.println(a1.getClass().getName()); //返回I ,见JDK System.out.println(a1.getClass().getSuperclass().getName()); //返回父类名称 System.out.println(a4.getClass().getSuperclass().getName()); Object aObj1 = a1; Object aObj2 = a4; //Object[] aObj3 = a1; Object[] aObj4 = a3; Object[] aObj5 = a4; System.out.println(a1); System.out.println(a4); System.out.println(Arrays.asList(a1));//[[I@42719c]整数没有转,这里必须接收Object数组形式 System.out.println(Arrays.asList(a4)); //[a, b, c, d]字符串就转了 //Object obj = null; pirintObject(a1); } //打印数组 private static void pirintObject(Object obj) { Class clazz = obj.getClass(); if(clazz.isArray()){ int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{ System.out.println(obj); } }
内省 --IntroSpector -->JavaBean--->特殊的Java类 JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。 如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO) PropertyDescriptor //import java.beans.PropertyDescriptor; 属性描述
在ReflectPoint中增加set,get方法
IntroSpectorTest.java
package ZHANG.Reflect; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class IntroSpectorTest { public static void main(String[] args) throws Exception { ReflectPoint pt1 = new ReflectPoint(3,5); String propertyName ="x"; //"x"--->"X"-->"getX"-->MethodGetX--> Object retVal = getProperty(pt1, propertyName); System.out.println(retVal); Object value = 7; setProperty(pt1, propertyName, value); System.out.println(pt1.getX()); } //Eclipse重构抽取方法 private static void setProperty(Object pt1, String propertyName, Object value) throws IntrospectionException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodSetX = pd2.getWriteMethod();// 获得应该用于set属性值的方法。 methodSetX.invoke(pt1, value); } //Eclipse重构方法获得 private static Object getProperty(Object pt1, String propertyName) throws IntrospectionException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodGetX = pd.getReadMethod();// 获得应该用于读取属性值的方法。 Object retVal = methodGetX.invoke(pt1); return retVal; } }
----采用遍历BeanInfo的所有属性方式来查找和设置某个ReflectPoint对象的属性. 调用了IntroSpector.getBeanInfo()方法 .封装了JavaBean的信息的。
BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); Object retVal = null; for(PropertyDescriptor pd : pds){ if(pd.getName().equals(propertyName)){ Method methodGetX = pd.getReadMethod(); retVal = methodGetX.invoke(pt1); break; } } return retVal;
Apache公司提供了beanutils工具包操作JavaBean,
Beanutils.getProperty(pt1,"x").getClass().getName();//返回String类型
BeanUtils.setProperty(pt1,"x","9"); //因为设置进去是以String. //如传到服务器一个int7是以字符串形式。
假设ReflectPoint增加一个 Date 属性 birthday = new Date();
BeanUtils.setProperty(pt1,"birthday.time","222"); //支持级联操作
Beanutils.getProperty(pt1,"birthday.time");
可以转换成map
map{age:33,name:heima} //java 7..
BeanUtils.setProperty(map,"birthday.time","222"); //map对象
另,PropertyUtils.setProperty(pt1,"x",9); //以int类型存储
------------------------反射的基本操作实例-------------------------------------------------
Person.java
package Reflect; public class Person { private String name; private int age; private static int total; private Person() { super(); total++; } private Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static int getTotal() { return total; } public static void setTotal(int total) { Person.total = total; } @Override public String toString() { return "name:"+name+",age:"+age; } }
测试类
package Reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Scanner; @SuppressWarnings("unchecked") public class TestReflection { public static void main(String[] args) { System.out.println("请输入类型名称:"); Scanner scan = new Scanner(System.in); String className = scan.next(); System.out.println("当前类型:"+className); try { Class c = Class.forName(className); //解析属性 Field[] fs = c.getDeclaredFields(); for(Field f : fs){ System.out.println("-----------------------"); System.out.println("属性:"+f.toString()); System.out.println("/t数据类型:"+f.getType()); System.out.println("/t属性名称:"+f.getName()); int mod = f.getModifiers(); //返回这个字段的修饰符 System.out.println("/t属性修饰符:"+ Modifier.toString(mod)); } //解析方法 Method[] ms = c.getDeclaredMethods(); for(Method m :ms){ System.out.println("-----------------------"); System.out.println("方法:"+m.toString()); System.out.println("/t方法名:"+m.getName()); int mod = m.getModifiers(); //返回这个字段的修饰符 System.out.println("/t方法修饰符:"+ Modifier.toString(mod)); System.out.print("/t方法参数列表:"); Class pts[] = m.getParameterTypes(); //参数列表 for(int i=0;i<pts.length;i++){ Class class1 = pts[i]; if(i!=0) System.out.print(","); //这里标逗号,值得借鉴 System.out.print(class1); } System.out.println(); System.out.println("/t返回值类型:"+m.getReturnType());// 方法的返回值类型 } System.out.println("-构造方法信息-----------------------------------"); //解析构造方法 Constructor[] cs = c.getConstructors(); for(Constructor con :cs){ System.out.println("-----------------------"); System.out.println("构造方法:"+con.toString()); System.out.println("/t构造方法名:"+con.getName()); int mod = con.getModifiers(); System.out.println("/t方法修饰符:"+ Modifier.toString(mod)); System.out.println("/t方法参数列表:"); Class pts[] = con.getParameterTypes(); //参数列表 for(int i=0;i<pts.length;i++){ Class class1 = pts[i]; if(i!=0) System.out.print(","); //这里标逗号,值得借鉴 System.out.print(class1); } System.out.println(); } System.out.println("------------------------------------"); //解析当前类型的父类 Class getSuper = c.getSuperclass(); System.out.println("当前父类:"+getSuper.toString()); System.out.println("----------------"); //当前实现的接口 Class[] interfaces = c.getInterfaces(); System.out.println("当前实现的所有接口:"); for(Class class1 : interfaces){ System.out.println(class1.toString()+"/t"); } System.out.println("/n------------------------------------"); //当前所在包信息 Package p =c.getPackage(); System.out.println("当前所在包:"+c.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
=====
User.java
package Reflect; public class User { public String name; public int age; public static int total=10; /* public User() { super(); total++; }*/ public User(String name, int age) { super(); this.name = name; this.age = age; total++; } public void setAll(String name,int age){ this.name = name; this.age = age; } public static void showTotal(){ System.out.println("int total showTotal,total="+total); } public String toString(){ return "用户名:"+name+",年龄:"+age; } }
测试
package Reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; public class TestRefUer { public static void main(String[] args) throws Exception { User u1 = new User("dd", 33); TestRefUer tf = new TestRefUer(); System.out.println("-------------------------------"); tf.mdf(u1, "name", "刷个"); tf.mdf(u1, "age", 13); System.out.println(u1); System.out.println("-------------------------------"); tf.mdf1("Reflect.User", "total", 44); System.out.println("-------------------------------"); // Class[] argtype = new Class[]{String.class,int.class}; Class[] argtype = {String.class,int.class}; //同上... Object[] argss = new Object[]{"王武",88}; tf.mdf2(u1, "setAll", argtype, argss); System.out.println(u1); System.out.println("-------------------------------"); tf.mdf4("Reflect.User", "showTotal", new Class[0], new Object[0]); } //直接操作对象属性 public void mdf(Object o,String fieldName,Object newValue) throws Exception{ Class c = o.getClass(); Field f = c.getField(fieldName); Object field = f.get(o); System.out.println("修改前:"+fieldName+"="+field); f.set(o, newValue); System.out.println("修改后:"+fieldName+"="+f.get(o)); } //直接操作类属性 public void mdf1(String o,String fieldName,Object newValue) throws Exception{ Class c = Class.forName(o); Field f = c.getField(fieldName); Object field = f.get(o); System.out.println("修改前:"+fieldName+"="+field); f.set(c, newValue); //这里操作的是class对象 System.out.println("修改后:"+fieldName+"="+f.get(c)); } //调用对象成员,赋值 public void mdf2(Object obj,String methodName,Class[] argType,Object[] args) throws Exception{ Class c = obj.getClass(); Method m = c.getMethod(methodName, argType); Object result = m.invoke(obj, args); //System.out.println(result); } //调用类成员方法 public void mdf4(String obj,String methodName,Class[] argType,Object[] args) throws Exception{ Class c = Class.forName(obj); Method m = c.getMethod(methodName, argType); Object result = m.invoke(null, args); //System.out.println(result); } }
=========调用构造方法
package Reflect; import java.lang.reflect.Constructor; public class TestRefUser2 { public static void main(String[] args) { Class c ; try { //调用有参构造方法 c = Class.forName("Reflect.User"); Class[] argTypes = {String.class,int.class}; //此处为User类的有参构造方法参数类型 Constructor cons = c.getConstructor(argTypes); Object obj = cons.newInstance("中国",5333); System.out.println(obj); //调用无参 cons =c.getConstructor(); //等同cons = c.getConstructor(new Class[0]); //cons = c.getConstructor(null); obj = cons.newInstance(); System.out.println(obj); //调用参构造方法2 obj = c.newInstance(); System.out.println(obj+"dd"); } catch (Exception e) { } } }
=========一个例子,用Hashtable存储对象======
package Reflect; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; //通过读取到文件中的值存储到Hashtable的KEY对象中去 public class TestRefHash { private static Hashtable mySession; static { mySession = new Hashtable(); mySession.put("stu", new User()); mySession.put("role", "monitor"); } public static void main(String[] args) throws Exception { Properties ps = new Properties(); FileInputStream fis = new FileInputStream("props.txt"); ps.load(fis); fis.close(); Enumeration pnames = ps.propertyNames(); while(pnames.hasMoreElements()){ String name = (String)pnames.nextElement(); String pvalue = ps.getProperty(name); //通过KEY获得值 TestRefHash.receiveParams("stu", name, pvalue); } System.out.println(TestRefHash.mySession.get("stu")); //打印键值 } public static void receiveParams(String beanName,String propertyName,String pValue)throws Exception{ Object o = mySession.get(beanName); //取得key返回的 User对象 Class c = o.getClass(); String methodName = "set"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1); if(methodName.equals("setAge")){ Method method = c.getMethod(methodName, new Class[]{int.class}); //int a =Integer.valueOf(pValue).intValue(); //System.out.println(pValue); pValue是int类型, 不能接收 //method.invoke(o, a); //设定对象方法上的set值 }else{ Method method = c.getMethod(methodName, new Class[]{java.lang.String.class}); method.invoke(o, pValue); //设定对象方法上的set值 } } }
====转换字符串INTEGER arraylist
final ArrayList<String> target = new ArrayList<String>(); target.add("sss"); target.add("bbb"); target.add("ccc"); Collection proxy = (Collection) Proxy.newProxyInstance(ArrayList.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] values) throws Throwable { if("add".equals(method.getName())){ return method.invoke(target, values); } return method.invoke(target, values); } }); proxy.add(12); proxy.add(33); for(Object o : proxy){ System.out.println(o.toString()); } System.out.println(proxy.size());import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ClassMethod { public static void main(String[] args) { Person p = new Person(); try { Method m = p.getClass().getMethod("println",null); m.invoke(p, null); m = p.getClass().getMethod("returns", null); String s = (String) m.invoke(p, null); System.out.println(s); m = p.getClass().getMethod("returns", String.class); s = (String) m.invoke(p, "hello"); System.out.println(s); } catch (Exception e) { e.printStackTrace(); } } } class Person { private String s = "s"; public void println(){ System.out.println("laiba"); } public String returns(){ return "hh"; } public String returns(String s){ return "sss"+s; } }