返回顶部

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();
            }
        }
    }
    
}

 

 

posted @ 2017-09-07 02:54  jaden好青年  阅读(135)  评论(0编辑  收藏  举报