使用反射生成并操作对象

一、获取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方法成功。

时间: 2024-12-25 09:49:38

使用反射生成并操作对象的相关文章

跟王老师学反射(五):使用反射生成并操作对象

跟王老师学反射(五):使用反射生成对象 主讲教师:王少华   QQ群号:483773664 学习内容 使用反射生成对象 模板类 一.创建对象 (一).非反射方法 (二).反射方式 通过构造方法生成对象,有二种方式,一种通过无参的构造方法,一种是通过有参的构造方法. 1.无参构造方法 1.1 如果无参数的构造方法是public 也可以使用Class对象的newInstance()方法来创建该Class对象对应类的实例 1.2 如果无参构造方法是私有化的 结论 如果无参构造访问,是私有化的,一定要使

JAVA基础知识之JVM-——使用反射生成并操作对象

Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法:可以获取构造器,由Constructor对象表示,调用Constructor对象的newInstance方法可以执行类对应的构造方法:可以获取成员变量,由Field对象表示,通过Field对象可以直接修改类的成员变量的访问权限和值. 创建对象 通过反射有两种方式创建对象 使用Class对象的newInstance(),这是最常用的方式,根据配置文件信息创建对象. 使用Class对象获取指定

反射生成对象,调用对象方法

反射生成对象1.使用newInstance()创建对象 要求有Class对象对应类的类有默认的构造方法,实际是利用默认构造方法来创建该类的实例 2.使用Constructor对象创建对象 获取该类的Class对象 使用Class对象获取值定的Constructor对象 再调用Constructor的newInstance()创建对象 可以使用指定的构造方法创建实例 调用方法invokeObject invoke(Object obj, Object...args)该方法中的obj是执行该方法的对

java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象

java反射并不是什么高深技术,面向对象语言都有这个功能. 面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象,去获取类相关的信息 2.利用java反射可以调用类的私有方法么?private()方法 答:可以,class取出method,method继承executable类,executable类继承AccessibleObject类,AccessibleObject有个setAccessiable()设置这个方法是否可访问. 则设置成true,就可将pr

Java反射获取类和对象信息全解析

反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题. 在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了. 获取类对象 Class.forName(String clazzName)静态方法 调用类的class属性,Person.class返回的就是Person的class对象(推荐使用) 调用某个对象的getClass()方法 具体使用还是要根据实际来选择,第一种方式是比较自由的,只要知道一个类名就可以了,其不会做该类是否存在的

生成系统操作日志

系统操作日志作用:主要是为了记录登录到系统中的人什么时间对什么模块的某条数据进行了操作.方便追踪操作责任. 本文讲的是基于log4j日志打印的,来生成系统操作日志.其实就是每次执行一个操作的时候调用了一个公共方法,将"登录人"."操作时间"."操作的模块及方法"保存到了数据库,用一张表来存储起来. 实现: 每个control继承BaseController.java package com.kentra.controller.base; impo

类的加载机制和反射——五、使用反射生成JDK动态代理

使用反射生成JDK动态代理 1.使用Proxy和InvocationHandler创建动态代理 (1)Proxy提供了用于创建动态代理类和动态代理对象的静态方法,他也是所有动态代理类的父类. (2)如果在程序中为一个或多个接口动态的生成实现类,就可以使用Proxy来创建动态代理类,如果需要为一个或多个接口动态的创建实例,也可以使用Proxy来创建动态代理实例. (3)Proxy提供了两个方法来创建动态代理类和动态实例: 1)static Class<?> getProxyClass(Class

读配置文件操作对象

前面学习了反射知识和xml文件的dom4j解析方法,下面的一个小案例就是综合了两种知识的运用: package cn.wwh.www.xml.do4j.exmple; /** *类的作用: * * *@author 一叶扁舟 *@version 1.0 *@创建时间: 2014-7-23   上午10:43:00 */ public class Student { private String name ; private int age; public Student(){} public S

Java生成和操作Excel文件(转载)

Java生成和操作Excel文件 JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过纯Java应用来处理Excel数据表.因为它是使用Java编写的,所以我们在Web应用中可以通过JSP.Servlet来调用API实现对Excel数据表的访问. 下载: 官方网站 http://www.andykhan.com/jexcelapi/ 下载最新版本(本