Java编程思想(十八) —— 再谈反射
来源:互联网 发布:dede数据库备份目录 编辑:程序博客网 时间:2024/05/15 16:30
在Java编程思想(十五) —— 类型信息之反射和Java编程思想(十六) —— 联系JVM再谈Class,书上只用了3页就讲完了,还有讲了那么多Class的东西,接下来要从反射中怎么用,自己结合API和其他资料再写多一些。
示例:Test.java
public class Test { public Test() { } public Test(int i) { System.out.println(i); } private void pri() {System.out.println("private");}public void pub() {System.out.println("public");}protected void pro() {System.out.println("protected");}private String pristr;public String pubstr;protected String pro;}
有不同的方法和域。
测试:
import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Reflect {public static void main(String[] args) {try {//测试参数类型后面跟着三点的作用Test t = new Test();t.three();t.three("a","b","c");//输出[] [a,b,c] 证明...表示的参数可以为空或者是传字符数组 即可传可不传 英文成为varargs//将Test装载进命名空间 得到代表Test的Class对象引用Class c = Class.forName("Test");//Method类 拿到名为pub的方法try {Method one = c.getMethod("pub");try {//方法调用 invoke(Object obj, Object... args) obj为所要调用方法所属的类 args为方法所传的参数//所传obj要为实例 ,不然会有object is not an instance of declaring classone.invoke(c.newInstance());} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}} catch (NoSuchMethodException e1) {e1.printStackTrace();} catch (SecurityException e1) {e1.printStackTrace();}//这种返回的方法的数组 为公共方法 包括那些父类和父接口中继承的方法Method[] method = c.getMethods();//返回的是该Class对象代表的类声明的所有方法 这样就包括public private protected方法 Method[] declaredmethod = c.getDeclaredMethods();Class[] array = c.getClasses();Field[] field = c.getFields();Field[] declaredfield = c.getDeclaredFields();for (int i = 0; i < array.length; i++) {System.out.println("Classes array is "+array[i].getName());}for (int i = 0; i < method.length; i++) {System.out.println("Methods array is "+method[i].getName());}//getReturnType拿到方法返回的属性。for (int i = 0; i < declaredmethod.length; i++) {System.out.println("DeclaredMethods array is "+declaredmethod[i].getReturnType().getName()+" "+declaredmethod[i].getName());try {try {String s[] ={"1","2"}; //如果没有设置 就会有Class Reflect can not access a member of class Test with //modifiers "private"异常//Constructor, Field, Method 为AccessibleObject的子类//有着访问控制的权限 默认是false 会强制java进行 访问检查 所以private是禁止访问的 Filed同理declaredmethod[i].setAccessible(true);System.out.println(declaredmethod[i].getName());if(declaredmethod[i].getName().equals("three")){System.out.println("true");//下面这条会报 wrong number of arguments异常 //这个问题是搞了我最久的东西 中文都是前篇一律的胡说八道//invoke(Object obj, Object... args) 数组是协变的 String[]被当成Object[]//String[] 被当成了整个参数 而string数组里面的元素又不是object //而不是args的第一个参数,其实,我们String数组是Objec数组的第一个元素/*这是因为编译器会把字符串数组当作一个可变长度参数传给对象o,而我们取得方法只有一个参数,所以就会出现wrong number ofarguments的异常,我们只要把字符串数组强制转换为一个Object对象就可以解决这个异常了 这个简直就是放屁*///declaredmethod[i].invoke(c.newInstance(),s);declaredmethod[i].invoke(c.newInstance(),new Object[]{s});declaredmethod[i].invoke(c.newInstance(),(Object)new String[]{"1","2","3"});declaredmethod[i].invoke(c.newInstance(),(Object)null);declaredmethod[i].invoke(c.newInstance(),(Object)new String[]{});}else{declaredmethod[i].invoke(c.newInstance());}} catch (InstantiationException e) {e.printStackTrace();}} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}//与Method同理,只不过Filed拿到的是域。for (int i = 0; i < field.length; i++) {System.out.println("Fields array is "+field[i].getName());}for (int i = 0; i < declaredfield.length; i++) {System.out.println("Declaredfieds array is "+declaredfield[i].getName());try {declaredfield[i].setAccessible(true);declaredfield[i].set(t, "a");} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}System.out.println(t.pro);System.out.println(t.pub);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
基本所有的问题和属性方法都在里面,不过wrong number of arguments异常,是我查了最久的异常,静下心来后看懂了。
这是因为编译器会把字符串数组当作一个可变长度参数传给对象o,而我们取得方法只有一个参数,
所以就会出现wrong number of arguments的异常,我们只要把字符串数组强制转换为一个Object对象就可以解决这个异常了。
全部都是这个错误的答案,invoke(Object obj, Object... args) ,数组是协变的 String[]被当成Object[]。
String[] 被当成了整个参数 ,而string数组里面的元素又不是object 。
而不是args的第一个参数,其实,我们String数组是Objec数组的第一个元素。
慢慢看就理解了。
后面补充:
Constructor<?>[] ct = Class.forName("Test").getConstructors();for (int i = 0; i < ct.length; i++) {System.out.println("Constructor:" + ct[i].getName());}System.out.println("new instance");try {ct[0].newInstance();ct[1].newInstance(123);} catch (InstantiationException | IllegalAccessException| IllegalArgumentException | InvocationTargetException e2) {e2.printStackTrace();}
Constructor就是构造器,不过不同于Class的newInstace方法,Constructor的newInstance(Object... initargs) 为varargs,即上面提到的三点。可以进行参数的传入。
而有趣的一点是,Constructor数组是有序的,前提是你的构造方法写在类里面最前面,如果前面有其他方法,那么数组的顺序就不是按照排序而排了。
反射的作用,就是运行时检查对象的类型,任意调用对象的方法(Spring和servlet中都用到了,注意到没有,我们在xml配置,然后属性会根据xml注入),同时可以知道方法参数和属性。
虽然这算是打破了所谓的封装性,private属性,不过想想,没有后门,语言岂不是死了?
对于反射,想了解跟多的可以看看国外的反射教程,http://www.programcreek.com/2013/09/java-reflection-tutorial/
- Java编程思想(十八) —— 再谈反射
- Java编程思想(十五) —— 类型信息之反射
- 42.java编程思想——反射 运行期类信息
- 《Java编程思想》学习笔记10——反射机制详解
- 51.scala编程思想笔记——浅尝反射
- java编程思想—chapter11.Zipcompress.java
- 《JAVA编程思想》读书笔记1——OOP思想
- 《Java编程思想》之类型检查(RTTI与反射机制)
- Java编程思想 - 类型信息与反射机制
- Java编程思想之类型信息(反射)
- java反射机制-一种必须掌握的编程思想
- 《java编程思想》——代码
- java 编程思想——基础篇
- JAVA编程思想——复用类
- Java编程思想读书笔记——字符串
- Java编程思想——泛型
- Java编程思想——第五章
- Java编程思想——第六章
- [leetcode] Gas Station
- Objective C 中的nil,Nil,NULL和NSNull理解
- 关于雅虎邮箱的Foxmail,outlook设置。
- oracle中的数据库、用户、方案、表空间、表对象之间的关系
- webstorm ftp配置
- Java编程思想(十八) —— 再谈反射
- LeetCode:Minimum Depth of Binary Tree
- win7中以管理员身份运行bat脚本时,获取当前文件所在目录
- Java 包(package)和import关键字
- 嵌入式 浅析Codewarrior、IAR和Keil MDK三大开发环境优缺点
- java/c/c++在线编译器
- 数据库层model使用基本类型 View层model使用封装类型
- javascript中Object.prototype.toString
- MyEclipse TCP/IP Monitor