基于反射的动态调用-不止是code和oop,还有类加载方案
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于反射的动态调用-不止是code和oop,还有类加载方案相关的知识,希望对你有一定的参考价值。
先给出基础类资源的代码,很容易理解,不做过多介绍:
1 package oop; 2 interface t { 3 public static final String name="zhangph"; 4 } 5 public class Father implements t{ 6 private static int mem; 7 static { 8 System.out.println("这是父类");//因为你不曾常用反射,所以加上这段代码显示区别 9 } 10 public Father() { 11 this.mem=258; 12 } 13 public String toString() { 14 return "there is the Object named father and the mem="+this.mem; 15 } 16 public void outPut() { 17 System.out.println("father function"+mem); 18 } 19 public void setMem(int m) { 20 this.mem=m; 21 } 22 public void test(int x) { 23 System.out.println("参数为"+x); 24 } 25 }
1 package oop; 2 import java.lang.reflect.Field; 3 public class Child extends Father{ 4 private static int mem; 5 static { 6 System.out.println("class is here"); 7 Static(); 8 System.out.println(mem); 9 } 10 public Child() { 11 System.out.println("子类版本构造函数"); 12 System.out.println("子类的mem初始值"+mem); 13 this.mem=2; 14 System.out.println("子类的mem最终值"+mem); 15 } 16 public void Cg() throws Exception { 17 this.mem=6; 18 System.out.println("子类的Cg方法"+mem); 19 } 20 public String toString() { 21 return "child"+super.toString(); 22 } 23 public static void Static () { 24 System.out.println("this is a static function"); 25 } 26 }
然后再介绍主函数:
1 package oop; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.Method; 4 import java.util.Random; 5 public class oop { 6 private static void Print( Object s) { 7 System.out.println(s.toString()); 8 } 9 public static void main(String []args) { 10 Class<?> cl1 = null,cl2=null,cl3=null; 11 try { 12 Print("1"); 13 cl1=Class.forName("oop.Father"); 14 } catch (ClassNotFoundException e) { 15 // TODO Auto-generated catch block 16 e.printStackTrace(); 17 } 18 Print("2"); 19 cl2=Father.class; 20 Print("3"); 21 cl3=new Father().getClass(); 22 Print("ls"); 23 Print(cl1.getName()); 24 Print(cl2.getName()); 25 Print(cl3.getName()); 26 Print("***********************"); 27 try { 28 Father f=(Father)cl1.newInstance(); 29 Field field=cl1.getDeclaredField("mem"); 30 field.setAccessible(true); 31 field.set(f,1234); 32 f.outPut(); 33 Method method1=cl1.getMethod("test",int.class); 34 method1.invoke(cl1.newInstance(),5); 35 Method method2=cl1.getMethod("outPut" ); 36 method2.invoke(cl1.newInstance()); 37 Method method3=cl1.getMethod("toString"); 38 String ss=(String) method3.invoke(cl1.newInstance()); 39 Print(ss); 40 } catch (InstantiationException | IllegalAccessException e) { 41 // TODO Auto-generated catch block 42 e.printStackTrace(); 43 }catch (NoSuchFieldException | SecurityException e) { 44 // TODO Auto-generated catch block 45 e.printStackTrace(); 46 }catch (Exception e) { 47 System.out.println("error"); 48 } 49 50 51 } 52 53 }
执行效果:
1
这是父类
2
3
ls
oop.Father
oop.Father
oop.Father
***********************
father function1234
参数为5
father function258there is the Object named father and the mem=258
下面着重分析第三个程序:
在第15、21、23行,你分别看到三种加载Class对象引用的方法。
forName()方法在编译时不会被检查,是完全的运行时调用,所以需要异常检查。对于Class对象引用,你可能之前接触很少(也许只是使用mysql包的时候接触过),但是它本身不难理解,类是程序的一部分,java中一切皆对象,所以自然而然每个类都对应着一个Class对象(泛型的),如你所知,每编译一个类,都会产生对应的.class文件。
我们知道,java程序在它开始运行之前并非完全被加载。
JVM的类加载系统会首先检查是否加载了.class文件的字节码,而JVM加载一个类的开始,一定是创建了对这个类的静态引用。
基于上面这句话,我们可以推断,构造方法也是静态方法。
我们回到15、21、23行,此时可以很明白的理解15和23行,23行是调用构造方法导入class类,forName方法直接加载.class对象。在forName方法中,我们也可以看到类体的静态语句被执行。
然后介绍21行,21行是使用一种叫做类字面常量的方法来生成的对Class对象的引用。这样做和使用forName的区别是它是在编译时检查的,所以不需要放在try块里面。同时,类字面常量的加载实现了足够的惰性,你可以看出,类字面常量并未加载类中的静态语句。
在25、26、27行中,我们可以看到Class对象引用的使用方法。实际上,Class对象引用有各种各样的get方法,例如
//getFields() 获取所有数据域
//getInterfaces() 获取实现的接口名
//getMethods() 获取所有的非构造函数
//getConstructors()获取构造函数
//getSuperclass()获取直接超类
下面介绍反射的调用规则。
在上面代码的30-41行,形象介绍了反射的使用方法。通过newInstance()生成对应类的对象引用,实际上这个方法的作用就类似于构造方法。同样,也通过getDeclaredField()方法修改静态域等。
在35到41行中,介绍了反射的普通方法调用,我分别举例了一个传参的和无参以及带返回值的方法,你可以类比其它。
以上是反射的核心部分内容,除了java编程思想,http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html这个博客对我理解以上内容有很大帮助。
关于反射的意义,反射的效率是低于普通构造方法的,但是它作为一种理念,即动态加载和自控制,是很值得学习的,同时,反射机制也是在处理大型程序编码中可能用到的,因为那个时候你对整个项目也许就不会了解的面面俱到了。
以上。
以上是关于基于反射的动态调用-不止是code和oop,还有类加载方案的主要内容,如果未能解决你的问题,请参考以下文章