黑马程序员_java反射

来源:互联网 发布:系统网络协议栈有损坏 编辑:程序博客网 时间:2024/06/05 00:22

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------


 

反射:通过字节码文件对象,调用Class类的方法获取构造方法对象、成员变量对象、成员方法的对象,再通过构造方法对象、成员变量对象、成员方法对象去调用Constructor,Field,Method方法间接,创建类对象,使用成员变量,使用方法的过程。

Blog1_1  获取字节码文件对象的方法:

通过上面定义可知,反射的前提是要获取一个类的字节码文件对象,那怎样来获取字节码文件对象呢,有三种方法可选:

(1)   通过Object类的getClass()方法;

由于Object是所有类的父类,如果Object具有getClass()方法,那就意味着所有的类都具有了getClass()方法,那我们就可以通过创建任何类的对象,来调用getClass()方法获取该类的字节码文件对象。如:

Person p=new Person();//创建了一个Person类的对象Class c=p.getClass();//调用getClass()方法获取到该类的字节码文件对象c

(2)   通过数据类型的class静态属性;

如:Class c=person.class;

可以获取该类的字节码文件对象,此种方法简单易用。但在开发中方法一、和方法二均不常用,常用下面方法:

(3)   通过class类静态方法forName(String className)

如:Class c=Class.forName(“student.wangyiyong_01.Person”);注意其中()里面的类名一定要是所需类的完全限定名,也就是要带上包名的路径。

Blog1_2 通过字节码文件对象创建构造器对象:

(1)   首先获取字节码文件对象:

Classc=Cass.forName(“student.wangyiyong_01.Person”);//创建了Person类的字节//码文件对象

(2)   通过字节码文件对象调用Class类方法创建构造器对象:

既然有了字节码文件对象,那肯定可以通过字节码文件对象调用Class类的一些方法,通过查找api发现了:getConstructor(Class<?>...parameterTypes)方法,…表示的可变参数的意思,是jdk5的新特性之一,Class<?>…parameterTypes就是传递参数个数可变的Class类型的参数。下面我们就通过实例来创建一个构造器的对象:

//首先创建字节码文件对象Class c=Class.forName(“student.wangyiyong_01.Person”);//有了字节码文件对象,查查Class类看有些什么方法,发现有getConstructor()方法Constructor con=c.getConstructor();//创建了构造器的对象,再通过构造器对象就可以间接的创建对象了Objec obj=Con.newInstance();//注意通过构造器对象创建的对象是object类型的必须用Object来接受。至此完成了一个重要的过程:创建字节码文件对象-----通过字节码文件对象创建构造器对象------通过构造器对象创建了对象。

Blog1_3 通过字节码文件对象创建成员变量对象并使用成员变量:

通过上面的例子我们发现反射其实就是不断的使用字节码文件对象创建对象,再调用方法创建对象的过程。

(1)   首先还是创建字节码文件对象

Class c=Class.forName(“student.wangyiyong_01.Person”);

(2)   通过字节码文件对象,调getField()方法,获取成员变量的对象

Field field=c.getField(“name”);//注意要加入方法名

(3)   得到了成员变量的对象,我们就可以使用成员变量的对象调用Field类的方法,使用成员变量和对成员变量进行赋值。如下:

Object o=field.get();//获取成员变量field.set(obj,”hello”);//对名为name的成员变量进行赋值,其中obj为前面Constructor构造器创建的对象。

Blog1_4 通过字节码文件对象创建成员方法对象并使用成员方法:

(1)   创建字节码文件对象

 Class c=Class.forName(“student.wangyiyong_01.Person”);

(2)   通过字节码文件对象调用Class类的getMethod方法创建成员方法对象

其中getMethod(String name,Class<?>...parameterTypes)括号里面第一项String name是需要获取方法对象的方法名,Class<?>…parameterTypes表示的是需要传递参数个数可变,参数类型为Class的参数。

Method  m=c.getMethod(“show”,String.class,int.class);//获取到了成员方法名为show的方法对象。

(3)   通过调用Method类的invoke方法使用方法。

m.Invoke(obj,”lining”,”48”);//通过Invoke方法使用了Person类的show方法。

其中obj还是前面Constructor构造器对象创建的对象。

Blog1_5 总结:

构造方法:获取字节码文件对象, 通过字节码文件对象获取构造器对象,通过构造器对象创建对象。

成员变量:获取字节码文件对象,通过字节码文件对象获取成员变量对象,通过成员变量对象调用方法给对象赋值。

成员方法:获取字节码文件对象,通过字节码文件对象获取成员方法对象,通过成员方法对象调用方法。

Blog1_6应用:

一个通过反射配合Properties集合,通过修改配置文件不改变原代码,使用不同类(Teacher、Student、Worker是三个都具有name,age属性的类)的例子:

Properties prop = new Properties();      FileReader fr = new FileReader("class.txt");      prop.load(fr);      fr.close();      // 根据已知键获取值      String className =prop.getProperty("className");      String methodName =prop.getProperty("methodName");      // 反射      Class c = Class.forName(className);      Constructor con = c.getConstructor();      Object obj = con.newInstance();      Method m = c.getMethod(methodName);      m.invoke(obj);

配置文件(class.txt)内容如下:

   className=Student

   methodName=show

整个程序中并没有出现Student s=new Student();Teacher t=new Teacher();

Worker w=new Worker();等使程序可闭性降低的代码,而只是简单的通过修改此配置文件,中className和methodNamed的值,可以做到在不改动源代码的情况下就使用不同的类,这样做无疑使程序的可维护性大大增强了。

 

----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------

详情请查看:http://edu.csdn.net/heima


0 0