- 浏览: 403685 次
- 性别:
- 来自: 秦皇岛
最新评论
-
prayjourney:
了解了,讲的不错
DataInputStream和DataOutputStream类 -
niunianss:
将字节退回的时候,需要添加判断,最后一个字符是英文时,实际数组 ...
PushbackInputStream -
cctt_1:
不要误人子弟,那根本就不是 解释器模式!!!那是Composi ...
Interpreter(解释器)模式 -
java-大神:
[i][i]引用引用引用引用[/img][/img][/img ...
BufferedReader和BufferedWriter -
百合不是茶:
你的程序在文件输入输出流中传入agrs[0]时,会报错越界 ...
DataInputStream和DataOutputStream类
1. 使用反射机制,可以在运行时期动态加载类并生成对象,操作对象上的方法、改变类成员的值,甚至连私有成员的值也可以改变。
2. 生成对象:可以使用Class的newInstance()方法来实例化一个对象,实例化的对象以Object类型返回。例如:
Class c = Class.forName(className); Object obj = c.newInstance();
下面是一个简单的示范,可以动态加载实现了List接口的类。
package ysu.hxy; import java.util.*; public class NewInstanceDemo { public static void main(String[] args) { try { Class c = Class.forName(args[0]); List list = (List)c.newInstance(); for(int i = 0;i < 5;i++) { list.add("element " + i); } for(Object o: list.toArray()) { System.out.println(o); } }catch(ClassNotFoundException e) { System.out.println("找不到指定的类"); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } } }
运行结果如下:
D:\hxy>java ysu.hxy.NewInstanceDemo java.util.ArrayList
element 0
element 1
element 2
element 3
element 4
实际上如果想要使用反射来动态加载类,通常是对对象的接口或者类型都一无所知,也就无法像上面范例中那样对newInstance()返回的对象进行接口转换动作。后面会介绍如何以反射来调用方法以操作newInstance()所返回的对象。
如果加载的类中具备无参数的构造函数,则可以无参数的newInstance()来构建一个不指定初始变量的对象。如果在动态加载及生成对象时指定对象的初始化变量,则要先指定参数类型、取得Constructor对象、使用Constructor的newInstance()并指定参数的接受值。
下面以一个例子来说明,先来定义一个Student类。
package ysu.hxy; public class Student1 { private String name; private int score; public Student1() { name = "N/A"; } public Student1(String name,int score) { this.name = name; this.score = score; } public void setName(String name) { this.name = name; } public void setScore(int score) { this.score = score; } public String getName() { return name; } public int getScore() { return score; } public String toString() { return name + ":" + score; } }
可以用Class.forName()来加载student1类,并使用第二个有参数的构造函数来构建student实例。如下所示:
package ysu.hxy; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class NewInstanceDemo2 { public static void main(String[] args) { try { Class c = Class.forName(args[0]); //指定参数类型 Class[] params = new Class[2]; //第一个参数是String params[0] = String.class; //第二个参数是int,在指定基本类型时要使用对应的包类并使用.TYPE。例如指定int类型时,使用Integer.TYPE,如果要指定Integer类型的参数,才是使用Integer.class。 params[1] = Integer.TYPE; //取得对应参数列的构造函数 Constructor constructor = c.getConstructor(params); //指定变量内容 Object[] argObjs = new Object[2]; argObjs[0] = "caterpillar"; argObjs[1] = new Integer(90); //给定变量并实例化 Object obj = constructor.newInstance(argObjs); //调用toString()来查看描述 System.out.println(obj); } catch(ClassNotFoundException e) { System.out.println("找不到类"); } catch(SecurityException e) { e.printStackTrace(); } catch(NoSuchMethodException e) { System.out.println("没有指定的方法"); } catch(IllegalArgumentException e) { e.printStackTrace(); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } catch(InvocationTargetException e) { e.printStackTrace(); } } }
注意,在指定基本类型时,要使用对应的包类(Wrapper)并使用.TYPE。例如指定int类型时,则使用Integer.TYPE,如果要指定Integer类型的参数,才是使用Integer.class。上面的范例会根据指定的变量调用对应的构造函数,运行结果如下:
D:\hxy>java ysu.hxy.NewInstanceDemo2 ysu.hxy.Student1
caterpillar:90
3. 调用方法:
使用反射可以取回类的方法的对象代表,方法的对象代表是java.lang.reflect.Method的实例,可以使用它的invoke() 方法来动态调用指定的方法。如调用上面Student1类的setName()方法,这里以下面范例作为示范:
package ysu.hxy; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class InvokeMethodDemo { public static void main(String[] args) { try { Class c = Class.forName(args[0]); //使用无参数构造函数建立对象 Object targetObj = c.newInstance(); //设定参数类型 Class[] param1 = {String.class}; //根据参数类型取回方法对象 Method setNameMethod = c.getMethod("setName",param1); //设定变量值 Object[] argObjs1 = {"caterpillar"}; //给定变量调用指定对象上的方法,使用方法代表的invoke()方法 setNameMethod.invoke(targetObj,argObjs1); Class[] param2 = {Integer.TYPE}; Method setScoreMethod = c.getMethod("setScore",param2); Object[] argObjs2 = {new Integer(90)}; setScoreMethod.invoke(targetObj,argObjs2); //显示对象描述 System.out.println(targetObj); } catch(ClassNotFoundException e) { System.out.println("找不到类"); } catch(SecurityException e) { e.printStackTrace(); } catch(NoSuchMethodException e) { System.out.println("没有这个方法"); } catch(IllegalArgumentException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } catch(InvocationTargetException e) { e.printStackTrace(); } catch(InstantiationException e) { e.printStackTrace(); } } }
运行结果:
D:\hxy>java ysu.hxy.InvokeMethodDemo ysu.hxy.Student1
caterpillar:90
此范例指定加载Student1类并生成实例,接着可以动态调用setName()与setScore()方法。范例中参数类型与变量值的设定与前面的范例是类似的,由于调用setName()和setScore()所给定的变量是caterpillar与90,故运行结果也是一样的。
很少的情况下,会需要突破Java的存取限制来调用受保护的或私有的方法(例如有一个组件,但没法修改它的源代码来改变某个私有方法的权限,又一定要调用某个私有方法),这时可以使用反射机制来达到目的。一个存取私有方法的例子如下:
Method privateMethod =
c.getDeclaredMethod("somePrivateMethod",new Class[0]);
privateMethod.setAccessible(true);
privateMethod.invoke(targetObj,argObjs);
使用反射来动态调用方法的实际例子之一是JavaBean的设定,例如在JSP/Servlet中,可以根据使用者的请求名称与JavaBean的属性名称自动比对,将字符串请求值设定至指定的JavaBean上,并自动根据参数类型作类型转换。下面是一个简单的示例,可以给CommandUtil工具类一个Map对象与类名称,然后取得一个更新了值的实例,其中参数Map对象的键为要调用的setter方法名称(不含set,如setName()方法,只要给定键为name即可),而值为要设定给setter的变量。
package ysu.hxy; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Map; public class CommandUtil { //给定Map对象及要产生的Bean类名称 //可以取回已经设定完成的对象 public static Object getCommand(Map requestMap,String commandClass) throws Exception { Class c = Class.forName(commandClass); Object o = c.newInstance(); return updateCommand(requestMap,o); } //使用reflection自动找出要更新的属性 public static Object updateCommand(Map requestMap,Object command) throws Exception { Method[] methods = command.getClass().getDeclaredMethods(); for(int i = 1;i < methods.length; i++) { //略过private、protected成员且找出必须是以set开头的方法名称 if(!Modifier.isPrivate(methods[i].getModifiers()) && !Modifier.isProtected(methods[i].getModifiers()) && methods[i].getName().startsWith("set")) { //取得不包括set的名称 String name = methods[i].getName().substring(3).toLowerCase(); //如果setter名称与键值相同 //调用对应的setter并设定值 if(requestMap.containsKey(name)) { String param = (String)requestMap.get(name); Object[] values = findOutParamValues(param,methods[i]); methods[i].invoke(command,values); } } } return command; } //转换为对应类型的值 private static Object[] findOutParamValues(String param,Method method) { Class[] params = method.getParameterTypes(); Object[] objs = new Object[params.length]; for(int i = 0;i < params.length;i++) { if(params[i] == String.class) { objs[i] = param; } else if(params[i] == Short.TYPE) { short number = Short.parseShort(param); objs[i] = new Short(number); } else if(params[i] == Integer.TYPE) { Integer number = Integer.parseInt(param); objs[i] = new Integer(number); } else if(params[i] == Long.TYPE) { Long number = Long.parseLong(param); objs[i] = new Long(number); } else if(params[i] == Float.TYPE) { Float number = Float.parseFloat(param); objs[i] = new Float(number); } else if(params[i] == Double.TYPE) { Double number = Double.parseDouble(param); objs[i] = new Double(number); } else if(params[i] == Boolean.TYPE) { Boolean number = Boolean.parseBoolean(param); objs[i] = new Boolean(number); } } return objs; } };
CommandUtil可以自动根据方法上的参数类型,将Map对象中的值对象转换为属性上的对应类型,目前它可以转换基本类型与String类型的属性。一个使用CommandUtil类的例子如下:
package ysu.hxy; import java.util.*; public class CommandUtilDemo { public static void main(String[] args) throws Exception { Map<String,String> request = new HashMap<String,String>(); request.put("name","caterpillar"); request.put("score","90"); Object obj = CommandUtil.getCommand(request,args[0]); System.out.println(obj); } }
可以使用此范例加载Student1类,使用CommandUtil.getCommand()方法可以返回一个设定好值的Student实例。虽然设定给request的值是字符串类型,但CommandUtil会使用反射机制来自动转换为属性上的对应类型。一个运行的范例如下:
D:\hxy>java ysu.hxy.CommandUtilDemo ysu.hxy.Student1
caterpillar:90
通过规范方法的命名方式,就可以再通过反射机制加上方法名称的比对,以正确调用对应的方法。
发表评论
-
内部类总结
2009-11-27 14:28 1179一、方法及作用域内的内部类:1.在一个方法内定义的类2.在一个 ... -
finalize()方法终结条件验证 示例代码
2009-09-20 09:23 1296package Initialization; clas ... -
Proxy(代理)模式二
2009-05-15 21:16 15172. 重新思考图像代理: 现在需要思考设计模式是否 ... -
Junit简介
2009-04-08 17:46 15521. 单元测试(Unit Test) 一个单元(Un ... -
Ant简介
2009-04-08 13:10 17401. Ant可以自动完成的任务: (1)编译Java源代 ... -
专题制作--文字编辑器(文字编辑与保存)
2009-04-08 10:43 21491. 文字编辑与保存: (1). 打开文件的处理流 ... -
专题制作--文字编辑器(逻辑实现部分)
2009-04-07 22:35 18531. 事件处理: 在Java中事件以具体的对象来表 ... -
专题制作--文字编辑器(接口部分)
2009-04-07 20:28 21031. Swing入门: 若要使用J2SE来开发窗口应用 ... -
信息绑定(国际化处理)
2009-04-07 20:02 15301. 程序中的一些文字信息可以将之定义在一个属性文件中,而不定 ... -
日志(Logging)
2009-04-07 16:14 16211. 日志(Logging) 程序不免会出现错误,当 ... -
Java中的日期和时间
2009-04-07 11:26 19111. 使用Date: 使用System.cu ... -
meta-annotation
2009-04-07 09:23 30161. 所谓meta-annotation就是Annotati ... -
Annotion
2009-04-06 23:05 16351. Annotation对程序运行没有影响,它的目的在于对编 ... -
使用反射生成与操作对象(二)
2009-04-06 17:04 17221. 修改成员值: 尽管直接存取类的域成员是不被鼓励的 ... -
Java中的反射(二)
2009-04-06 10:42 19801. 当在命令行模式下执行java XXX.class 指令后 ... -
Java中的反射(一)
2009-04-06 09:43 12901. Java提供的反射机制允许您在运行时动态加载类、查看类信 ... -
容器类的线程安全及ThreadLocal类
2009-04-05 21:28 30161. 容器类默认没有考虑 ... -
wait()和notify()
2009-04-05 19:06 13221. wait()、notify()、notifyAll() ... -
Java线程之同步化(Synchronized)主题
2009-04-05 16:44 26741. 如果一个对象所持有的数据可以被多线程同时共享存取,必须 ... -
Java线程(三)
2009-04-05 15:37 18531. Java中的每个线程都 ...
相关推荐
Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作.docx
反射对象生成sql,保存对象。 里面还差,存储过程、批量操作、动态sql 还差一个配套的工具(根据数据库字段生成对象)
主要介绍了Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
那么书写操作数据库的代码很简单:只需呼叫FacadeForDAO.findModel(表名)方法,在表名参数给出实际数据库中表的名称就可以返回一个包含对应POJO类的对象的集合--非常简单--输入表名得到Java对象的集合,然后根据需要...
反射是一种间接操作目标对象的机制,在程序程序运行时获取或者设置对象自身的信息。 只要给定类的名字,就可以通过反 射获取类的所有信息,接着便能调用它的任何一个方法和属性。 反射的步骤有哪些? 第一:获取类...
是一款专门为VB/C#.Net数据库程序员开发量身定做的(ORM框架)代码生成工具,所生成的代码基于面向对象、分层架构设计、ORM并参考微软Petshop中的经典思想,使用改进的抽象工厂设计模式及反射机制等。目前直接支持...
C#.Net实体代码生成工具(EntitysCodeGenerate)是一款专门为 C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想和分层架构设计,并参考了微软Petshop中经典的思想和设计模式,融入...
是一款专门为 C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想、分层架构设计及ORM,并参考了微软Petshop中经典的思想,融入了工厂模式等设计模式,反射机制等。从数据库中提取...
每当一個类被载入时,JVM就自动为其生成一个Class对象,通过操作class对象,我们可以得到该对象的所有成员并操作它们 public class ClassDemo { public static void main(String[] args) { String name = “ACCP"; ...
是一款专门为 C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想、分层架构设计及ORM,并参考了微软Petshop中经典的思想,融入了工厂模式等设计模式,反射机制等。从数据库中提取...
是被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息并能直接操作任意对象的内部属性及方法。 java反射机制所提供的功能: 生成动态代理 在运行时判断任意一个对象所属的类 在...
我们创建一个类,通过编译,生成对应的.calss文件,之后使用java.exe加载(jvm的类加载器)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在缓存区,那么这个运行时类的本身就是一个class的实例 ...
对于任意一个对象,都能够调用它的任意一个方法,常见的应用如下 逆向代码 ,例如反编译 与注解相结合的框架 例如Retrofit 单纯的反射机制应用框架 例如EventBus 2.x 动态生成类框架 例如Gson Java高级程序设计实战...
VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】是一款专门为VB/C#.Net数据库程序员开发量身定做的(ORM框架)代码生成工具,所生成的代码基于面向对象、分层架构、ORM,使用改进的抽象工厂设计模式及反射机制...
Codematic (2.0版)是一款为 C# 数据库程序员设计的自动代码生成器,Codematic 生成的代码基于基于面向对象的思想和三层架构设计,结合了Petshop中经典的思想和设计模式,融入了工厂模式,反射机制等等一些思想。...
摘要:VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】是一款专门为.Net数据库程序开发量身定做的(ORM框架)代码生成工具,所生成的程序代码基于面向对象、分层架构、ORM及反射+工厂设计模式等。支持.Net1.1...
DbToCode 是一款为 C# 数据库程序员设计的自动代码生成器,DbToCode 生成的代码基于基于面向对象的思想和三层架构设计,结合了Petshop中经典的思想和设计模式,融入了工厂模式,反射机制等等一些思想。采用 Model +...
是一款专门为VB/C#.Net数据库程序员开发量身定做的代码生成工具,所生成的代码基于面向对象、分层架构设计、ORM并参考微软Petshop中的经典思想,使用改进的抽象工厂设计模式及反射机制等。工具目前直接支持Oracle、...
生成的代码基于面向对象的思想和三层架构设计,结合了目前最经典的设计思想和设计模式,融入了工厂模式,反射机制等等一系列操作。能实现对ACCESS,mysql,SQLSERVER2000,ORACLE等多种数据库进行操作,提供了 SQL查询...
傲世源代码生成器是一款为C#数据库程序员设计的自动代码生成器,傲世源 生成的代码基于面向对象的思想和三层架构设计,结合了目前最经典的设计思想和设计模式,融入了工厂模式,反射机制等等一系列操作。能实现对...