JAVA加强——反射&内省

                         反射

一、概述
1.定义:反射就是将java的各种成分映射成为相应的类,对映射的类可以进行相应的操作。
2.反射的基石:
Class:java程序中的各个类属于同一个事物,这个事物的名称就是Class

    理解:众多的人可以用Person表示,那么众多的java类可以用Class表示

3.如何得到Class的实例对象:

    1.类名.class
    2.对象.getclass()
    3.Class.forName(String)

注意:
1.int.class==Integer.Type boolean.class==Boolean.Type……只要在源程序中出现的类型,都有对应的Class实例对象(即对应的字节码文件,如void.class,int[].class)
2.同一类在内存中只有一个字节码文件对象(.class文件)

二、Class的成员的反射

1.构造方法的反射:
Class类中:

   T newInstance()        创建空参数的新实例
   Constructor<T> getConstructor(Class<?>... parameterTypes) 
                          返回一个 Constructor 对象,它反映此所表示的类的指定公共构造方法
   Constructor<?>[] getConstructors() 
                              返回一个包含类的所有公共构造方法                    
   Constructor getDeclaredConstructor(Class<>parameterTypes) 
                          返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
   Constructor<?>[] getDeclaredConstructors() 
                          返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法
   String getName()        以字符串形式返回此字节码的名称 
   Class<?>[] getInterfaces()        返回该类所实现接口的数组

Constructor类中:

    T newInstance(Object... initargs) 
              使用此 Constructor 对象创建该构造方法新实例,并用指定的初始化参数初始化该实例
    Class<?>[] getParameterTypes() 
              按照声明顺序返回 Class 对象的数组,这些对象描述了此 Class对象所表示的方法的形参类型
    String getName()        以字符串形式返回此Class对象所表示实体的名称 

2.对成员变量的反射:

        public int x,private int y; 
        Class c = pt1.getClass();
        Field fieldX = c.getField("x");
        Object object = fieldX.get(pt1);

        对私有成员(或者default)的暴力反射
        Field f = c.getDeclaredField("y");
        f.setAccessible(true);
        Object object = f.get(pt1);

通过反射修改成员变量的值:

        成员变量必须是public的
        Field[] fields = obj.getClass().getFields();
        for(Field field:fields) {
            if(field.getType() == String.class){
                String oldValue =(String)field.get(obj);
                String newValue = oldValue.replace('d', 'a');
                field.set(obj, newValue);
            }
        如果是private,或者default:
        Field[] fields = obj.getClass().getDeclaredFields();
                for(Field field:fields) {
                    if(field.getType() == String.class){
                        field.setAccessible(true);
                        String oldValue = (String)field.get(obj);
                        String newValue = oldValue.replace('d', 'a');
                        field.set(obj, newValue);
                    }

3.对成员方法的反射:

        String str = "avc";
        Class c = Class.forName("java.lang.String");
        //获取到要操作的方法
        Method method = c.getMethod("charAt", int.class);
        //方法的调用,如果方法时静态的method.invoke(null, 22)
    System.out.println(method.invoke(str, 2));

4.对某个类的main方法的反射:

//运行时传递一个类名的参数arg[0]
        String name = args[0];
        Class c1 = Class.forName(name);
        Method mainmethod = c1.getMethod("main", String[].class);
        mainmethod.invoke(null, new String[]{"111","222"});
        //会报异常,原因是参数个数不对(编译器会按照jdk1.4的语法将数组拆分成若干个参数,调用main就出错了)
        //解决办法: mainmethod.invoke(Object obj, Object ...args);
        1.mainmethod.invoke(null, (Object)new String[]{"111","222"});
        2.mainmethod.invoke(null, new Object[]{new String[]{"111","222"}});
        //这里编译器会做特殊处理,不会把参数当做数组看待,也就不会分散成若干个参数。

5.对数组的反射:
1.具有相同的维数和类型的数组,是同一种字节码

private static void printArry(Object obj) {
        Class  c = obj.getClass();
        if(c.isArray()) {
            int length = Array.getLength(obj);
            for(int i=0;i<length;i++) {
                System.out.println(Array.get(obj, i));
                }
    }else {
        System.out.println(obj);

2.ArrayLsit.asList(Object[] obj)

            如果传递int[],打印的是(类名@hashcode),因为int[]不是一个Object[],javac会按照jdk1.5将int[]数组搞成一个对象
            如果传递String[],打印的是数组里面的内容,因为Stirng[]是Object[]数组,jdk要兼容低版本的javac,会走jdk1.4.

注意:通过反射无法获得数组的类型,只能获得数组里面的对象的类型

                           内省

一、概述
内省(Introspector):是一种特殊的java类,主要用于传递属性信息,这种java类中的方法主要用于访问私有的字段,并且符合某种规则命名。

    如果一个类符合这种特点,我们可以称这个类为javaBean,我们可以按照普通的类来操作,也可把它作为一个javabean处理。

二、操作

1、PropertyDescriptor类(java.beans):PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。

构造函数:
PropertyDescriptor(String propertyName, Class<> beanClass) 
   通过调用 getFoo 和 setFoo 存取方法,为符合标准 Java 约定的属性构造一个 PropertyDescriptor

常用方法:
Method getReadMethod()        获得应该用于读取属性值的方法 
Method getWriteMethod()        获得应该用于写入属性值的方法

2.简单操作

public static void main(String[] args) throws Exception {
        ReflectPoint rp1 = new ReflectPoint("chenhong", 23);
        String propertyName = "name";
        String propertyName1 = "age";
        Object object = getProperties(rp1, propertyName);
        System.out.println(object);
        Object object1 = getProperties(rp1, propertyName1);
        System.out.println(object1);
        String value = "chenxi";
        Object value1 = new Integer(30);
        setProperties(rp1, propertyName1, value);
    }
    //修改属性的值
    private static void setProperties(Object rp1, String propertyName1,Object value) throws Exception{
        //构造属性描述器PropertyDescriptor对象 
        PropertyDescriptor pd1 = new PropertyDescriptor(propertyName1, rp1.getClass());
        //获取"写"方法
        Method method = pd1.getWriteMethod();
        //调用"写"方法,指定相应的值
        method.invoke(rp1, value);
    }
    //获取属性的值
    private static Object getProperties(Object rp1, String propertyName) throws Exception {
        //构造属性描述器PropertyDescriptor对象 
        PropertyDescriptor= new PropertyDescriptor(propertyName, rp1.getClass());
        //获取"读"方法
        Method method = pd.getReadMethod();
        //调用方法,获取其值
        return method.invoke(rp1, null);
    }

4、beanutils工具包操作JavaBean

1.导入BeanUtils工具包:加入jar包到工程中,引入commons-logging包的支持

2.方法:
BeanUtils.getProperties()
BeanUtils.setProperties()//对属性都是进行字符串操作
PropertyUtils.getProperties()//对属性本身类型进行操作
PropertyUtils.setProperties()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值