Java基础--反射、内省

反射就是把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;  
    }  
  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值