码迷,mamicode.com
首页 > 其他好文 > 详细

使用反射生成并操作对象

时间:2016-04-27 22:41:33      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:

一、获取Class对象的方式

Java中,每个类被加载到内存中,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类,获得Class对象有三种方式:

1.使用Class类的forName(String clazzName)静态方法,该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名。

2.通过某个类的class属性获取,例如Person.class。

3.调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法,所以所有的Java对象都可以调用该方法,该方法将会返回该对象所属类对应的Class对象。

对于第一种和第二种方法,都是直接根据类来取得该类的Class对象,相比之下,第二种方式有以下优势:

代码更安全,程序在编译阶段就可以检查需要访问的Class对象是否存在。

程序性能更好,因为这种方式无需调用方法。

二、通过反射创建对象的方式

有两种方式:

1.使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法时实际上是利用默认构造器来创建该类的实例。

2.先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例。

三、调用方法

当获得某个类对应的Class对象后,就可以通过该Class对象的getMethods()方法或者getMethod()方法来获取全部方法或者指定方法。

每个Method对象对应一个方法,获得Method对象后,程序就可通过该Method来调用它对应的方法,在Method里面包含一个invoke()方法,该方法的签名如下:

Object invoke(Object obj,Object... args):该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参。

下面写一个例子,对象池工厂,简单模拟一下Spring框架的IoC思想。

obj.txt中:

a=java.util.Date
b=javax.swing.JFrame
b%title=Title

主代码:

package demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class ObjectPoolFactory {
    //定义一个对象池
    private Map<String, Object> objectPool = new HashMap<String, Object>();
    private Properties props = new Properties();
    
    /**
     * 定义一个创建对象的方法
     * @param clazzName
     * @return
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private Object createObject(String clazzName) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
        //根据字符串获取对应的class对象
        Class clazz = Class.forName(clazzName);
        //使用clazz对应类的默认构造器创建实例
        return clazz.newInstance();
    }
    
    /**
     * 初始化properties对象
     * @param fileName
     * @throws IOException
     */
    public void init(String fileName) throws IOException{
        FileInputStream fis = new FileInputStream(fileName);
        props.load(fis);
    }
    
    /**
     * 根据指定文件来初始化对象池
     * 它会根据配置文件来创建对象
     * @throws IOException 
     * @throws IllegalAccessException 
     * @throws InstantiationException 
     * @throws ClassNotFoundException 
     */
    public void initPool() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{
        
        for (String name : props.stringPropertyNames()) {
            //每取出一对key-value对,就根据value创建一个对象
            //调用createObject()创建对象,并将对象添加到对象池中
            System.out.println(name);
            if(!name.contains("%")){
                objectPool.put(name, createObject(props.getProperty(name)));
            }
        }
    }
    
    /**
     * 该方法根据属性文件来调用指定对象的setter方法
     * @throws SecurityException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @throws IllegalArgumentException 
     * @throws IllegalAccessException 
     */
    public void initProperty() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        for (String name : props.stringPropertyNames()) {
            //key用于控制对象的setter方法设置值
            //%前面是对象名字,后面是setter方法名
            if(name.contains("%")){
                String[] strs = name.split("%");
                Object target = getObject(strs[0]);
                String method = "set" + strs[1].substring(0, 1).toUpperCase() +
                        strs[1].substring(1);
                //获取对象实现类多对应的Class对象
                Class targetClass = target.getClass();
                //获取希望调用的setter方法
                Method mtd = targetClass.getMethod(method, String.class);
                //通过Method的invoke方法执行setter方法
                mtd.invoke(target, props.getProperty(name));
            }
        }
    }
    
    /**
     * 获取对象
     */
    public Object getObject(String name){
        //从objectPool中取出指定name对应的对象
        return objectPool.get(name);
    }
    
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        ObjectPoolFactory pf = new ObjectPoolFactory();
        pf.init("obj.txt");
        pf.initPool();
        pf.initProperty();
        System.out.println(pf.getObject("a"));
        System.out.println(pf.getObject("b"));
    }
    
    
}

运行结果:

b
a
b%title
Wed Apr 27 21:51:20 CST 2016
javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=Title,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

窗口的名字也传进来了,说明调用setter方法成功。

 

使用反射生成并操作对象

标签:

原文地址:http://www.cnblogs.com/DarrenChan/p/5440549.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!