Java基础--反射、内省

来源:互联网 发布:怎么当淘宝店铺客服 编辑:程序博客网 时间:2024/05/22 01:54

反射就是把Java类中的各种成分映射成相应的Java类

 例如,一个Java类中用一个Class类的对象来表示,

一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,
就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,

这些信息就是用相应类的实例对象来表示,它们是Field(成员变量)、Method(方法)、Contructor(构造方法)、Package等等。


个人对反射的理解
pt1.getClass()获取到的是一个Class对象,这个对象不同于new出来的对象,有点类似于继承的子父类的关系,
pt1.getClass()获取到的对象相当于父类对象,是一个由class类直接获取到的Class对象,而不同于new出来的对象
pt1.getClass().getField("y")是通过这个Class对象获取到这个class类里面成员变量的一个操作权限,但只是获取了一个权限,没什么实际的用处
必须通过get获取set方法获取到操作某个对象的操作权限


用生活中的例子理解:
就像修手机的人,一个修手机的人他只会修手机的屏幕,就是说明这个人拥有修手机屏幕的权限,就相当于pt1.getClass().getField("y");所获取到的对y的控制权限
但是有些手机在还有没有生产出来之间,这个人就已经会修理屏幕了,很符合反射的原理,在对象还没有new出来之前他就已经拥有了控制y的权限
但是你会修手机屏幕,但没有手机也是不行的,没有东西修,一定要有一个手机给你修才行,手机就相当于new出来的对象


如何得到各个字节码对应的实例对象( Class类型)
类名.class,例如,System.class
对象.getClass(),例如,new Date().getClass()
Class.forName("类名"),例如,Class.forName("java.util.Date");

九个预定义Class实例对象:八个基本数据类型加一个void
参看Class.isPrimitive方法的帮助
Int.class == Integer.TYPE


//反射  import java.lang.reflect.Array;  import java.lang.reflect.Constructor;  import java.lang.reflect.Field;  import java.lang.reflect.Method;    public class ReflecDemo {          public static void main(String[] args) throws Exception{          // TODO Auto-generated method stub          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(cls1 == cls3);          System.out.println(cls1);                    /*             boolean isPrimitive()              判定指定的 Class 对象是否表示一个基本类型。           * */          System.out.println(cls1.isPrimitive());//判断是否是基本数据类型对象          System.out.println(int.class.isPrimitive());          System.out.println(int.class == Integer.class);//false          System.out.println(int.class == Integer.TYPE);//true,将Integer.TYPE后就是基数据类型了          System.out.println(int[].class.isPrimitive());//false数组不是基本数据类型          System.out.println(int[].class.isArray());//true,判断数组要用isArray                              int[] a1 = new int[]{1,5,8};          int[] a2 = new int[4];          int[][] a3 = new int[3][4];          String[] a4 = new String[]{"a","c","b","d"};          System.out.println(a1.getClass() == a2.getClass());          //System.out.println(a1.getClass() == a4.getClass());          //System.out.println(a1.getClass() == a3.getClass());          System.out.println(a1.getClass().getName());          System.out.println(a1.getClass().getSuperclass().getName());          System.out.println(a4.getClass().getSuperclass().getName());                    Object aObj1 = a1;          Object aObj2 = a4;          Object[] aObj4 = a3;          Object[] aObj5 = a4;                                                  ArrayDemo(a4);          ArrayDemo("zxc");      }            //反射中数组的演示      public static void ArrayDemo(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);          }      }                  //反射中Method(方法)的演示      public static void MethodDemo() throws Exception{          //getMethod(String name, Class<?>... parameterTypes)           //返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。          //name 参数是一个 String,用于指定所需方法的简称          //parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。                     //invoke(Object obj, Object... args)           //对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。          String str1 = "abc";          Method methodCharSt = String.class.getMethod("charAt", int.class);//int.class为所获取方法所接收的数据类型,可用于分别重载方法          System.out.println(methodCharSt.invoke(str1, 1));//使用反射使用charAt方法返回1位置上的值          //invoke(null, 1) 如果第一个参数为null,则调用的是静态方法      }                        //反射中Field(成员变量)的演示和说明      public static void FieldDemo() throws Exception{          ReflectPoint pt1 = new ReflectPoint(3,5);          //getField,返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段          Field fieldY = pt1.getClass().getField("y");//getField的参数为字段名          System.out.println(fieldY.get(pt1));//得到fieldY在pt1这个对象上的值          /*个人对反射的理解          pt1.getClass()获取到的是一个Class对象,这个对象不同于new出来的对象,有点类似于继承的子父类的关系,          pt1.getClass()获取到的对象相当于父类对象,是一个由class类直接获取到的Class对象,而不同于new出来的对象          pt1.getClass().getField("y")是通过这个Class对象获取到这个class类里面成员变量的一个操作权限,但只是获取了一个权限,没什么实际的用处                                     必须通过get获取set方法获取到操作某个对象的操作权限          * */                              //getDeclaredField,返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。          Field fieldX = pt1.getClass().getDeclaredField("x");//获取已被私有的成员变量用getDeclaredField          //setAccessible,将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。          //值为 false 则指示反射的对象应该实施 Java 语言访问检查。          fieldX.setAccessible(true);//暴力反射          System.out.println(fieldX.get(pt1));                    //演示使用反射替换字符串          changeStringValue(pt1);          System.out.println(pt1);      }            public static void changeStringValue(Object obj) throws Exception{          Field[] fields = obj.getClass().getFields();//获取Field操作权限          for (Field field : fields){              if (field.getType() == String.class){                  String oldValue = (String)field.get(obj);//对obj对象的Field进行操作,获取值                  String newValue = oldValue.replace('b','a');                  field.set(obj, newValue);              }          }      }                  //反射中构造方法的演示      public static void ConstructorDemo() throws Exception{                    /*          * Constructor类代表某个类中的一个构造方法             得到某个类所有的构造方法:             例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();                          得到某一个构造方法:             例子:Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);             //获得方法时要用到类型                          创建实例对象:             通常方式:String str = new String(new StringBuffer("abc"));             反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));             //调用获得的方法时要用到上面相同类型的实例对象            * */                              //new String(new StringBuffer("abc"));          Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//获取构造方法(根据参数来确定获取那个构造方法)          //使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。          String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));          System.out.println(str2.charAt(2));      }    }  



内省



简单的说内省就是在javaBean中通过反射的机制来使用get,set方法


import java.beans.IntrospectionException;  import java.beans.PropertyDescriptor;  import java.lang.reflect.*;  import java.util.*;  import org.apache.commons.beanutils.BeanUtils;  import org.apache.commons.beanutils.PropertyUtils;    public class IntroSpectorDemo {        /**      * @param args      */      public static void main(String[] args) throws Exception{          // TODO Auto-generated method stub          ReflectPoint pt1 = new ReflectPoint(3, 5);                    String propertyName = "x";          //获取值          Object retVal = getProperty(pt1, propertyName);          System.out.println(retVal);          //使用架包          System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());                              //设置值          Object value = 7;          setPropertes(pt1, propertyName, value); //自动抽取方法,右键-->refactor-->Excract Method             BeanUtils.setProperty(pt1, "x", 9);          System.out.println(pt1.getX());                    /*         //java7新特性         Map map = (name:"zxx",age:18);         BeanUtils.setProperty(map,"name", "lhm");         */                    BeanUtils.setProperty(pt1, "birthday.time", "111");          System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));                              PropertyUtils.setProperty(pt1, "x", 9);          System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());      }                  //PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。      //使用PropertyDescriptor不同于反射或者getX的区别在于,getX只能访问public权限的,      //而PropertyDescriptor则可以访问所有权限,包括private      private static void setPropertes(Object pt1, String propertyName,              Object value) throws IntrospectionException,              IllegalAccessException, InvocationTargetException {                    PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, pt1.getClass());          //getWriteMethod  获得应该用于写入属性值的方法。           Method methodeSetX = pd2.getWriteMethod();          methodeSetX.invoke(pt1,value);      }        private static Object getProperty(Object pt1, String propertyName)              throws IntrospectionException, IllegalAccessException,              InvocationTargetException {                    PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());          //getReadMethod()  获得应该用于读取属性值的方法。          Method methodeGetX = pd.getReadMethod();          Object retVal = methodeGetX.invoke(pt1);          return retVal;      }    }  


0 0
原创粉丝点击