《JAVA反射(23页).doc》由会员分享,可在线阅读,更多相关《JAVA反射(23页).doc(24页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、-刚开始学习java的时候真的很难理解反射到底是个什么东西一些书籍,哪怕是很经典的书籍都解释的让人感觉懵懵的,或许的确是我太笨况且,网上说在将来学习框架的时候需要经常应用到反射机制,这样一来总让人心里有些不安就方才偶然又把讲解反射的章节和视频看了一点,觉得能理解一些了现在决定一鼓作气,边看边写,顺便把一些主要的内容和操作都记载到这里我想,对于我这么一个笨笨的人来说,学习的最好方法也许就是不断重复遇到不懂的知识就停下来把以往的重新学一遍,虽然浪费了很多时间,但对我也有些效果我的理解是:所谓反射,就是根据一个已经实例化了的对象来还原类的完整信息至少对我而言,我认为它带给我的好处是,让我从下往上的又
2、了解了一遍面向对象x_x 在此又痛恨一边那些厚部头们,把我的脑细胞搞死一片Class类如果要完成反射,那么必须了解Class类实例1:通过对象取得包名和类名12345678910111213packageorg.siu;classTest publicclassDemo publicstaticvoidmain(String args) Test t =newTest();System.out.println(t.getClass();System.out.println(t.getClass().getName();编译结果如下,注意包的编译方式即可此处的getClass()方法是默认继承自
3、Object类的在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例因此,这样一来就会牵扯到向上转型和向下转型的概念由于向下转型的不安全因素,在这里泛型也会接踵而来(不过我想说的是,此处的泛型设计很刺眼!尼玛,整个java的语法设计同样刺眼,超恶心!)实例2:Class类的实例化由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式: 对象.getClass( ) 类.Class forName( )123456789101112131415161718192021222324252627classTest publicclass
4、Demo publicstaticvoidmain(String args) /方式一:Test t =newTest();Class c1 = t.getClass();System.out.println(c1);/方式二:/为了避免特殊性,这里不用Test类,而用java库中的String类Class c2 = String.class;System.out.println(c2);/方式三:/forName()方法会抛出异常Class c3 =null;tryc3 = Class.forName(Test);catch(ClassNotFoundException e) e.print
5、StackTrace();System.out.println(c3);其中,forName( )方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性Class类的应用Class类中有一个方法叫做newInstance( ),它可以用来创建一个Class类对象的新实例怎么说呢?Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)实例3:Class类的无参构造对象12345678910111213141516171819202122232425publicclassDemo publicstaticvoidmain(String args) /实例
6、化Class对象,forName()方法会抛异常Class c =null;try/这里需要完整的包名和类名c = Class.forName(java.lang.String);catch(ClassNotFoundException e) e.printStackTrace();/生成一个字符串的引用String s =null;try/将构造好的对象向下转型为String类/newInstance()方法会抛异常s = (String) c.newInstance();catch(InstantiationException e) e.printStackTrace();catch(Il
7、legalAccessException e) e.printStackTrace();System.out.println(字符串长度: + s.length();这样就通过无参数的形式构造了一个新的对象,如同正常模式中通过无参构造方法来构造新对象一样我们知道,类中除了有无参构造方法,还会存在有参数的构造方法那在反射中如何通过有参数的形式构造对象呢?接着看实例4:Class类的有参构造对象1234567891011121314151617181920importjava.lang.reflect.Constructor;publicclassDemo /下面的几个方法抛出来的异常太多,为了代
8、码的紧凑性,这里就直接抛给虚拟机了publicstaticvoidmain(String args)throwsException Class c =null;tryc = Class.forName(java.lang.String);catch(ClassNotFoundException e) e.printStackTrace();char ch = h,e,l,l,o;String s =null;/获得Class类对象的有参构造方法,括号里面参数的写法是:类型.classConstructor con = c.getConstructor(char.class);/用此构造方法构造
9、一个新的字符串对象,参数为一个char数组s = (String) con.newInstance(ch);System.out.println(构造的字符串:+ s);我们还是使用String类做例,因为String类用的比较多,便于理解这里需要注意的是,构造方法需要使用getConstructor( )方法获得至于参数类型则是:原有类型.class还有一点,无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在那么,如何才能知道原有类里面的构造方法,普通方法,继承的父类等详细信息呢?接着看获取类的结构要通过反射获取类的结构我们这里要导入一个新的包java.lang.reflec
10、t实例5:取得类的构造方法123456789101112131415161718importjava.lang.reflect.Constructor;importjava.util.Arrays;publicclassDemo /下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了publicstaticvoidmain(String args)throwsException Class c =null;tryc = Class.forName(java.lang.Boolean);catch(ClassNotFoundException e) e.printStackT
11、race();/这里的getConstructors()方法返回的是一个Constructor数组Constructor cons = c.getConstructors();/打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看System.out.println(Arrays.toString(cons);我选择了Boolean类来做例,因为Boolean类的构造方法就两个,方便看实例6:取得类所实现的接口1234567891011121314importjava.util.Arrays;publicclassDemo publicstaticvoidmain(
12、String args)throwsException Class c =null;tryc = Class.forName(java.lang.Boolean);catch(ClassNotFoundException e) e.printStackTrace();Class in = c.getInterfaces();System.out.println(Arrays.toString(in);没什么好说的,看结果实例7:取得父类12345678910111213publicclassDemo publicstaticvoidmain(String args)throwsExceptio
13、n Class c =null;tryc = Class.forName(java.lang.Boolean);catch(ClassNotFoundException e) e.printStackTrace();/注意了,这里不会是数组,why?Class su = c.getSuperclass();System.out.println(su);别忘了,java中是单继承,父类只有一个实例8:取得类的全部方法1234567891011121314151617importjava.lang.reflect.Method;publicclassDemo publicstaticvoidmai
14、n(String args)throwsException Class c =null;tryc = Class.forName(java.lang.Boolean);catch(ClassNotFoundException e) e.printStackTrace();Method m = c.getMethods();/好吧,这次我就大发慈悲的写个打印列表出来for(inti =0; i m.length; i+) System.out.println(mi);截取一部分,看看,意思下就行了这几个例子都比较简单实例9:取得本类的全部属性123456789101112131415161718
15、192021importjava.lang.reflect.Field;classPerson privateString name;privateintage;publicclassDemo publicstaticvoidmain(String args)throwsException Class c =null;tryc = Class.forName(Person);catch(ClassNotFoundException e) e.printStackTrace();Field f = c.getDeclaredFields();for(inti =0; i f.length; i+
16、) System.out.println(fi);getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性实例10:获取本类中属性的值1234567891011121314151617181920212223242526272829303132importjava.lang.reflect.Field;classPerson publicString name;privateintage;publicPerson(String name,intage) this.name = name;this.age = age;publicclassDemo pu
17、blicstaticvoidmain(String args)throwsException Person p =newPerson(zhangsan,12);Class c = p.getClass();/获取公共属性的值Field f1 = c.getField(name);/get(p)表明要获取是哪个对象的值String str = (String) f1.get(p);System.out.println(姓名: + str);/获取私有属性的值Field f2 = c.getDeclaredField(age);/age是私有属性,所以要设置安全检查为truef2.setAcces
18、sible(true);intage = (int) f2.get(p);System.out.println(年龄: + age);要注意的是:setAccessible()方法可以设置是否访问和修改私有属性坦白说,java学到现在我还没发现什么能亮瞎我钛金眼的知识在里边每次都是写一堆繁琐的语法实现个小玩意儿,不然就是拼命调用API,拼命的抛异常让本身显得不够紧凑的代码变得愈发累赘如果我喜欢一门语言,在我利用它做出东西来之前,它本身的特性必须能够打动我显然,java并不让我快乐,也许很多程序员跟我一样是被迫使用java的仅以此来安抚我那颗孤独编码的心,下面接着看内容反射的应用实例11:通过反
19、射修改属性12345678910111213141516171819202122232425262728importjava.lang.reflect.Field;classPerson privateString name;publicPerson(String name) this.name = name;publicString toString() return姓名: +this.name;publicclassDemo publicstaticvoidmain(String args)throwsException Person p =newPerson(王二狗);System.ou
20、t.println(p);Class c = p.getClass();/定义要修改的属性Field f = c.getDeclaredField(name);f.setAccessible(true);/修改属性,传入要设置的对象和值f.set(p,张二蛋);System.out.println(p);几个方法都是有联系的,如果看不懂就先熟悉上面几个例子实例12:通过反射调用方法123456789101112131415161718192021222324252627importjava.lang.reflect.Method;classPerson publicvoidprint(inti
21、) System.out.println(我在写数字: + i);publicstaticvoidsay(String str) System.out.println(我在说: + str);publicclassDemo publicstaticvoidmain(String args)throwsException Person p =newPerson();Class c = p.getClass();/getMethod()方法需要传入方法名,和参数类型Method m1 = c.getMethod(print,int.class);/invoke()表示调用的意思,需要传入对象和参数
22、m1.invoke(p,10);Method m2 = c.getMethod(say, String.class);/这里的null表示不由对象调用,也就是静态方法m2.invoke(null,你妹);这里演示了一个普通的有参方法和一个静态方法既然有参数的都写出来了,那么无参的就更简单了,直接传入一个对象即可实例13:通过反射操作数组123456789101112131415161718192021importjava.lang.reflect.Array;publicclassDemo publicstaticvoidmain(String args)throwsException int
23、 arr = 1,2,3,4,5;Class c = arr.getClass().getComponentType();System.out.println(数组类型: + c.getName();intlen = Array.getLength(arr);System.out.println(数组长度: + len);System.out.print(遍历数组: );for(inti =0; i len; i+) System.out.print(Array.get(arr, i) + );System.out.println();/修改数组System.out.println(修改前的第一个元素: + Array.get(arr,0);Array.set(arr,0,3);System.out.println(修改后的第一个元素: + Array.get(arr,0);这里要注意一点,getComponentType( )返回的是数组元素的Class暂时就写这么多,我看的书中还有反射在工厂模式中的应用无非是用forName()方法替换一下,没什么可说的我是个java初级黑,我恨java那种恶心的语法和设计这都是为了Android,为了打基础,为了适应以后的工作Fuck java第 24 页-
限制150内