• Java反射机制


    反射获取属性、构造、方法

    获得类的字节码对象:Class对象.三种获得的方式.
    * 类名.class;
    * 类的实例.getClass();
    * Class.forName();
    获得构造器:Constructor
    获得属性:Field
    获得方法:Method

    package com.boomoom.demo3.reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    import org.junit.Test;
    
    /**
     * 反射的测试的案例:
     * @author admin
     * 反射的目的是为了操作某个类的属性或方法
     *
     */
    public class ReflectDemo1 {
    
        @Test
        /**
         * 获得代表这个类加载到内存的字节码文件的对象Class对象.
         */
        public void demo1() throws ClassNotFoundException{
            // 一种:通过类名.class
            Class clazz1 = Person.class;
            // 二种:通过类的实例对象.getClass()方法获得.
            Person person = new Person();
            Class clazz2 = person.getClass();
            // 三种:使用Class的forName的静态方法获得.(推荐使用这种)
            Class clazz3 = Class.forName("com.boomoom.demo3.reflect.Person");
        }
        
        @Test
        /**
         * 通过反射操作其构造方法:
         * DBUtils: Person person = queryRunner.query(sql,new BeanHanlder(Person.class));
         */
        public void demo2() throws Exception{
            // 反射第一步获得Class对象.
            Class clazz = Class.forName("com.boomoom.demo3.reflect.Person");
            // 采用默认的无参数的构造方法创建:
            // Person person = (Person) clazz.newInstance();
            // person.run();
            // 采用有参数的构造方法来创建对象:Person p = new Person("张森",38);
            Constructor c = clazz.getConstructor(String.class,Integer.class);
            Person p = (Person) c.newInstance("张森",38);
            System.out.println(p.name);
            System.out.println(p.age);
        }
        
        @Test
        /**
         * 通过反射获得类中的属性:
         */
        public void demo3() throws Exception{
            // 反射第一步获得Class对象.
            Class clazz = Class.forName("com.boomoom.demo3.reflect.Person");
            // 获得属性:
            // 以下两种仅仅获得共有的属性:
            // clazz.getField("name"); // 获得某个属性
            // Field[] fields = clazz.getFields(); // 获得所有属性
            // 获得私有的属性: p.name = 
            Field field1 = clazz.getDeclaredField("name");
            field1.setAccessible(true);
            Field field2 = clazz.getDeclaredField("age");
            field2.setAccessible(true);
            Constructor c = clazz.getConstructor(String.class,Integer.class);
            Person p = (Person) c.newInstance("张森",42);
            String name = (String) field1.get(p);
            Integer age = (Integer)field2.get(p);
            System.out.println(name+"   "+age);
        }
        
        @Test
        /**
         * 通过反射获得类中的方法:并且让方法执行.
         * 
         */
        public void demo4() throws Exception{
            // 反射第一步获得Class对象.
            Class clazz = Class.forName("com.boomoom.demo3.reflect.Person");
            // 获得类中的方法:
            Method method = clazz.getDeclaredMethod("run");
            method.setAccessible(true);
            method.invoke(clazz.newInstance());// p.run();
            
            // 获得带有参数的方法:
            Method method2 = clazz.getDeclaredMethod("sayHello", String.class);
            String s = (String) method2.invoke(clazz.newInstance(), "凤姐"); // String s = p.sayHello("凤姐");
            System.out.println(s);
        }
        
        /**
         * Servlet的执行过程:
         *   <servlet>
                <servlet-name>ServletDemo1</servlet-name>
                <servlet-class>com.boomoom.demo2.servlet.ServletDemo1</servlet-class>
              </servlet>
              <servlet-mapping>
                <servlet-name>ServletDemo1</servlet-name>
                <url-pattern>/ServletDemo1</url-pattern>
              </servlet-mapping>
              
              Class clazz = Class.forName("com.boomoom.demo2.servlet.ServletDemo1");
              // Servlet servlet = (Servlet)clazz.newInstance();
              Method method = clazz.getMethod("service",HttpServletRequest.class,HttpServletResponse.class);
              method.invoke(clazz.newInstance(),request,response);
              
              <package >
                  <action name="/hello" class="com.boomoom.action.HelloAction" />
              </package>
              
              <class name="com.boomoom.domain.User">
              
              </class>
         */
    }

    内省

    public void demo1() throws Exception{
            // 获得了Bean的信息
            BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
            // 获得Bean的属性描述了
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            for(PropertyDescriptor pd:pds){
                System.out.println(pd.getName());
                /*pd.getReadMethod(); // 获得get方法
                pd.getWriteMethod();// 获得set方法.*/        
            }
    }

    commons-beanutils-1.8.3.jar 是Apache出的 其 Populate 方法用来给对象中的属性赋值(BeanUtils.populate(p,map);)。参数1: 要设置属性的对象;参数2: 将属性以Map集合的形式传入Key : 属性的名称,Value: 属性具体的值。

    使用内省自己封装一个MyBeanUtils:

    package com.boomoom;
    
    import java.lang.reflect.Field;
    import java.util.Map;
    import java.util.Set;
    
    public class MyBeanUtils {
        private MyBeanUtils() {}
        
        //public static void setProperty(Object bean,String name,Object value)
        public static void setProperty(Object bean,String name,Object value) throws ReflectiveOperationException {
            //根据JavaBean对象获取对应的字节码对象
            Class clazz = bean.getClass();
            //根据字节码对象获取对应的Field对象
            Field f = clazz.getDeclaredField(name);
            //设置权限,让虚拟机不进行访问的检查
            f.setAccessible(true);
            //赋值
            f.set(bean, value);
        }
        //public static String getProperty(Object bean,String name)
        public static String getProperty(Object bean,String name) throws ReflectiveOperationException {
            Class clazz = bean.getClass();
            Field f = clazz.getDeclaredField(name);
            f.setAccessible(true);
            Object obj = f.get(bean);
            return obj.toString();
        }
        
        //public static void populate(Object bean,Map map)
        public static void populate(Object bean,Map map) throws ReflectiveOperationException {
            //通过JavaBean对象来获取对应的字节码对象
            Class clazz = bean.getClass();
            //获取Map中所有的key
            Set keys = map.keySet();
            for (Object key : keys) {
                
                try {
                    //根据key来获取对应的Field对象
                    Field f = clazz.getDeclaredField(key.toString());
                    //根据key来获取Map中对应的value
                    Object value = map.get(key);
                    
                    f.setAccessible(true);
                    f.set(bean, value);
                } catch(NoSuchFieldException e) {
                    //e.printStackTrace();
                }
            }
        }
        
    }

  • 相关阅读:
    log P1242 新汉诺塔
    Spring学习笔记
    spring之BeanFactory
    1.3.7、CDH 搭建Hadoop在安装之前(端口---第三方组件使用的端口)
    1.3.5、CDH 搭建Hadoop在安装之前(端口---Cloudera Search使用的端口)
    1.3.3、CDH 搭建Hadoop在安装之前(端口---CDH组件使用的端口)
    1.3.4、CDH 搭建Hadoop在安装之前(端口---Impala使用的端口)
    1.3.2、CDH 搭建Hadoop在安装之前(端口---Cloudera Navigator加密使用的端口)
    1.3、CDH 搭建Hadoop在安装之前(端口)
    1.3.1、CDH 搭建Hadoop在安装之前(端口---Cloudera Manager和Cloudera Navigator使用的端口)
  • 原文地址:https://www.cnblogs.com/boomoom/p/10141087.html
Copyright © 2020-2023  润新知