博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用反射生成并操作对象
阅读量:7100 次
发布时间:2019-06-28

本文共 4897 字,大约阅读时间需要 16 分钟。

一、获取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.Dateb=javax.swing.JFrameb%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
objectPool = new HashMap
(); 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")); } }

运行结果:

bab%titleWed Apr 27 21:51:20 CST 2016javax.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://gtkhl.baihongyu.com/

你可能感兴趣的文章
目标检測的图像特征提取之(一)HOG特征
查看>>
MySQL-EXPLAIN用法详解
查看>>
jdbctemplate中的query(sql,params,mapper)与queryForList(sql,params,class)区别
查看>>
C++ 虚函数表解析
查看>>
Responder一点也不神秘————iOS用户响应者链完全剖析
查看>>
Type mismatch: cannot convert from java.sql.PreparedStatement to com.mysql.jdbc.PreparedStatement
查看>>
thinkphp 重定向redirect
查看>>
Builder创建者模式
查看>>
安卓应用使用QQ登录的申请流程
查看>>
Android批量图片加载经典系列——采用二级缓存、异步加载网络图片
查看>>
redis 数据类型详解 以及 redis适用场景场合
查看>>
RAC安装重新运行root.sh
查看>>
Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.2(转)
查看>>
Java多线程有哪几种实现方式? Java中的类如何保证线程安全? 请说明ThreadLocal的用法和适用场景...
查看>>
工作队列(workqueue) create_workqueue/schedule_work/queue_work
查看>>
size_t、ptrdiff_t【转】
查看>>
Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 ...
查看>>
【Linux】查看所使用的Linux系统是32位还是64 位的方法
查看>>
NSJSONSerialization 反序列化失败 NSCocoaErrorDomain Code=3840
查看>>
chrome 谷歌浏览器插件损坏
查看>>