为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

java反射机制

2017-09-20 17页 doc 41KB 10阅读

用户头像

is_496339

暂无简介

举报
java反射机制java反射机制 Java 反射机制 1,介绍 Java 的反射机制是使其具有动态特性的非常关键的一种机制,通过java反射机制,可以动态分析一个类的属性及行为,也是在JavaBean 中广泛应用的一种特性。 2,Class类介绍 Java的反射机制是通过对Class类的操作进行的,在程序运行期间,运行时系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息保存着每个对象所属的类足迹。 3. 获取Class类 获取Class类有三种方法,下面分别介绍: (1) 调用一个类对象的getClass方法,将返回这个...
java反射机制
java反射机制 Java 反射机制 1,介绍 Java 的反射机制是使其具有动态特性的非常关键的一种机制,通过java反射机制,可以动态一个类的属性及行为,也是在JavaBean 中广泛应用的一种特性。 2,Class类介绍 Java的反射机制是通过对Class类的操作进行的,在程序运行期间,运行时系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息保存着每个对象所属的类足迹。 3. 获取Class类 获取Class类有三种方法,下面分别介绍: (1) 调用一个类对象的getClass方法,将返回这个对象所属类的Class类型。 (2) 调用Class类的forName方法,它的参数是一个字符串,当字符串代表的不是 一个类或接口的时候,调用forName方法会抛出一个checkedexception。所以无 论何时使用这个方法都应该提供一个异常处理。 (3) 如果T代表任意Java类型(T即可以是类也可以是基本的数据类型)。 如:Class class1 = int.class;(基本数据类型) Class class2 = Date.class;(类) Class class3 = int[].class;(类) Class的newInstance()方法,作用是返回这个类的一人实例,由于这个方法没有提供参数,所以构造类对象时是调用的相应类的默认构造方法。在这时一定要注意异常处理,测试代码如下: package reflect; public class SampleReflect { public String info; /** * @return the info */ public String getInfo() { return info; } /** * @param info the info to set */ public void setInfo(String info) { this.info = info; } /**print Info * */ public void printInfo() { System.out.println("Information : " + this.info); } public static void main(String[] arg) { Class cla1 = null; String classType = "reflect.SampleReflect"; try { cla1 = Class.forName(classType); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("没有找到类 : " + classType); } System.out.println("第二种方法得到Class : " + cla1.getName()); //调用方法printInfo SampleReflect sr1 = null; try { sr1 = (SampleReflect) cla1.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("不能实例化对象。\n请确认你要实例化的类不是一个抽象类或接口。"); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("发生对类非法访问的异常"); } //调用SampleReflect类的printInfo方法 sr1.setInfo("我是用Class的forName方法加载的"); sr1.printInfo(); //打印sr1.getClass的getName及SampleReflect.class的getName方法返回值 System.out.println("第一种方法得到Class : " + sr1.getClass().getName() + "\n" + "第三种方法得到Class : " + SampleReflect.class.getName()); } } 4, 利用反射分析类的能力 在java.lang.reflect包中有三个类Field、method、Constructor分别用于描述类的域、方法及构造器,且他们都有一个getName()方法用来返回相应项目的名称。Field类有一个getType方法,用来返回描述域所属类型的Class对象。这三个类还有一个getModifiers的方法,返回一个整数用于描述public、private及protected等描述。可以调用Modifier类相应静态方法来判断是什么修饰符。 Class类的getFileds、getMethods及getConstructors同getDeclareFields、getDeclareMethods 及getDeclareConstructors的区别:前者返的都是用public修饰的项目,而后都返的全部项目,但想想也明白,不包括超类的项目。 下面的代码对main函数的第一个参数代表的类进行分析,并输出到控制台所有的域、构造器及方法。代码AnalyseClass如下: package reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.TypeVariable; public class AnalyseClass { /** * @param cla */ public AnalyseClass(Class cla) { this.cla = cla; this.printConstructors(); this.printMethods(); this.printFields(); } //待分析的类 Class cla = null; /**打印类声明的所有构造器 * @return 声明的构造器的个数 */ public int printConstructors() { System.out.println("\n****constructors of Class " + this.cla.getName() + "****"); Constructor[] cons = cla.getDeclaredConstructors(); int counter = 0; for(Constructor c : cons) { ++counter; String name = c.getName(); String modifiers = Modifier.toString(c.getModifiers()); if(modifiers.length() > 0) { System.out.print(modifiers + " " + name + "("); } Class[] types = c.getParameterTypes(); for(int j = 0;j < types.length; ++j) { if(j > 0) System.out.println(","); System.out.print(types[j].getName()); } System.out.println(");"); } return counter; } /**打印类声明的所有方法 * @return 声明的方法的个数 */ public int printMethods() { System.out.println("\n****methods of Class " + this.cla.getName() + "****"); Method[] methods = cla.getDeclaredMethods(); int counter = 0; for(Method m : methods) { ++counter; String name = m.getName(); String modifiers = Modifier.toString(m.getModifiers()); if(modifiers.length() > 0) { System.out.print(modifiers + " " + name + "("); } Class[] types = m.getParameterTypes(); for( int j = 0; j < types.length; ++j) { if(j > 0 ) System.out.print(","); System.out.print(types[j].getName()); } System.out.println(");"); } return counter; } /**打印类声明的域 * @return 声明的域的个数 */ public int printFields() { System.out.println("\n****fields of Class " + this.cla.getName() + "****"); Field[] fields = cla.getDeclaredFields(); int counter = 0; for(Field f : fields) { String name = f.getName(); String modifiers = Modifier.toString(f.getModifiers()); if(modifiers.length() > 0) { System.out.println(modifiers + " " + name + ";"); } ++counter; } return counter; } public static void main(String[] args) { if(args.length > 0) { Class cla = null; try { cla = Class.forName(args[0]); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("没有找到类 : " + args[0]); return; } new AnalyseClass(cla); }else { System.out.println("请附带类"); } } } 对于上述的分析类的程序,打印构造器、域及方法时可以直接调用相应的toString()方法。 5.执行方法 对于类SampleReflect加入下面测试代码,用Method的invoke方法执行方法。 如果invoke的是一个静态方法,第一个隐式参数可以不写,但若不是静态方法时,第一个隐式参数就必须填了,为要执行的对象的object引用。 try { Method m1 =cla1.getMethod("setInfo",String.class); if(m1 != null) { m1.invoke(sr1, "通过Method的invoke方法进行的调用"); } } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 6. 在运行时使用反射分析对象 在编写程序时,如果知道要查看的域名和类型,查看指定的域是一件很容易的事情。而利用反射机制可以查看在编译时还不清楚的对象域。 主要使用了Field类的get(Object)方法,当Field为私有域时,会抛出IllegalAccessException。反射机制默认行为受限于java的访问控制。然而,如果一个java程序没有受到安全管理器的控制,就可以履盖访问控制。为了达到这个目的,需要调用Field、 Method、Constructor对象的setAccessible方法。 //访问控制 Field f = null; try { f = cla1.getField("info"); f = cla1.getDeclaredField("info"); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("非法访问"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("没有这个域"); } if (f != null) { try { System.out.println("域info的值为 : " + f.get(sr1)); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("不能访问"); } } 由于域info的修饰符是public,故上面的代码可以成功运行。但如果把info变为private 时,就会产生异常:NoSuchFieldException 。因为getField只能得到被声明为public的项目,故得不到info这个域。所以这里要用getDeclaredField方法来得到info域。 7.使用反射实现运算表达式的计算 代码如下: import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; public class DyComp { String expr = null; // private static com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); public static double execute(String expr) { DyComp dc = new DyComp(expr); double result = -99999; try { result = dc.result(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } //私有构造 private DyComp(String expr) { this.expr = expr; } public double result() throws IOException { String javafileContent = "import java.io.*;\r\n" + "public class ExpreDyComp {" + "\r\n" + "public static double cal() {\r\n" + "\tdouble var = " + this.expr + ";\r\n" + "return var;\r\n" + "}\r\n}"; System.out.println("待生成的文件内容" + "\n" + javafileContent); File tmpFile = new File("ExpreDyComp.java"); tmpFile.createNewFile(); PrintWriter printWriter = new PrintWriter(new FileWriter(tmpFile)); printWriter.write(javafileContent); printWriter.flush(); printWriter.close(); //对文件进行编译 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); int compRes = compiler.run(null, null, null,"-d","bin","ExpreDyComp.java"); if(compRes != 0) { System.out.println("编译出错"); } Class exprClass = null; try { exprClass = Class.forName("ExpreDyComp"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); System.err.println("找不到相应类"); } Method m = null; try { if(exprClass != null) { m = exprClass.getMethod("cal"); } } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(m != null) { try { Double d = (Double)m.invoke(null); //System.out.println("值为" + d.doubleValue()); return d.doubleValue(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return -9999; } private double readResultToFile(File inFile) throws IOException { BufferedReader bf = new BufferedReader(new FileReader(inFile)); String content = bf.readLine(); double res = 0; if(content != null) { res = Double.parseDouble(content); } else { System.out.println("文件" + inFile.getAbsolutePath() + "无数 据"); } bf.close(); return res; } public static void main(String args[]) { System.out.println("动态编译"); System.out.println("输入你要计算的表达式"); InputStreamReader inputReader = new InputStreamReader(System.in); BufferedReader bfReader = new BufferedReader(inputReader); String expre = null; try { expre = bfReader.readLine(); } catch (IOException e1) { // TODO Auto-generated catch block System.out.println("从键盘输入出现问"); e1.printStackTrace(); } //定义结果数据 double result = -99999; result = execute(expre); //打印到console System.out.println(expre + "计算结果如下" + "\n" + result); } } 附:继承设计的技巧 (1) 将公共操作和域放在超类。 (2).不要使用受保护的域。 (3) 使用继承实现is-a关系。 (4) 除非所有继承的方法都有意义,否则不要使用继承。 (5) 在履盖方法不要改变预期的行为。 (6) 使用类型信息而非类型信息。 (7) 不要过多的使用反射。
/
本文档为【java反射机制】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索