黑马程序员--反射技术

来源:互联网 发布:2014淘宝双11成交额 编辑:程序博客网 时间:2024/06/15 17:48

http://edu.csdn.net/heima android培训http://edu.csdn.net/heima ; java培训期待与您交流!

1、反射:反射就是把java类中的各个成分映射成相应的java类。

java反射机制是在运行状态,对任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

简单理解:反射技术可以对类进行解剖。

2、反射的做用:实现框架的功能。

    在开发中我们往往是基于某个框架的基础上进行开发,这样可以提高开发的效率,反射技术能让我们在框架的基础上方便我们添加新的功能。

3、什么是框架?

    一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文关系。因此构件库的大规模重用也需要框架。

4、获取Class的三种方式:

方式一:通过对象的getclass()方法获取。这种方式需要创建对象。

例如:new Person().getClass()

方式二:通过任意类型调用获取。这种方式不需要创建对象。 

       例如:class,System.class.

方式三:通过class类的forName(类名)方法获取。

       例如:Class.forName("java.util.Date");

5class类:

    java程序中的各个java类属于同一事物,描述这类事物的类就是Class。也就是用于描述字节码文件对象的类,这个类的实例表示正在运行的java应用程序中的类和接口,这个类的实例不需要用new来创建。

6、创建对象的过程。

new Person()对象的过程:

1、查找并加载Person.class文件进内存,并将该文件封装成Class对象。

2、再依据Class对象创建该类的Person实例。

3、调用构造函数对对象进行初始化。

直接创建对象代码示例:

Person p = new Person();

用反射对象创建Person对象的过程:

1、查找并加载指定名字的字节码文件进内存,并封装成Class对象。

2、通过Class对象newInstance方法创建对应字节码文件的实例。

3、使用构造函数对对象进行初始化。

反射创建对象代码示例:

String className = "cn.itcast.bean.Person";

Class clazz = Class.forName(className);

Object obj = clazz.newInstance();

7Class类中的方法:

forName(String className)获取字节码文件对象。

创建对象:

T newInstance()创建此Class对象表示的类的一个新实例。

获取Field对象:

Field getField(String name)只能获取公有,和父类公有的。

Field getDeclaredField(String name)只能获取本类中的,包括似有的。

Field[] getFields()能获取Class中的所有字段对象,包括继承,不包括似有。

Field[] getDeclaredFields()能获取所有字段,包括似有,不包括继承。

获取Method对象:

Method getMethod(String name,Class<?>... parameterTypes):(参数时方法名,参数类型)只获取公共的,包括父类公共的。

Method DeclaredMethod(String name,Class<?>... parameterTypes)获取所有,包括似有。不包括父类。

method[] getMethods()获取所有公有的Method方法对象,包括父类。

method[] getDeclaredMethods():获取所有包括似有的Method对象,不包括父类。

获取构造器:

getConstructor(Class<?>... parameterTypes):返回指定Class,指定参数的构造器。

getConstructor():返回所有的公共的构造器。

getDeclaredConstructor(Class<?>... parameterTypes):返回指定Class,指定参数的构造器,包括似有。

Field类中的方法:

给字段赋值:

void set(Object obj,Object value):明确了是哪个Field对象,设置指定值。

获取字段值:

Object get(Object obj):返回指定对象上此 Field 表示的字段的值。

AccessibleObject类:

void setAccessible(boolean):对该对象进行权限设置。(可以对似有属性的进行暴力访问)

Method类:

invoke(Object obj, Object... args): 调用方法,参数明确的是具体对象和传入的实际参数。

     相当于调用方法,并传入相应的实际参数。

数组与Object的关系以及反射类型:数组的父类都是Object。

    具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。也就是说他们的字节码都是同一份。

    int[] a1 = new int[3];

    int[] a2 = new int[4];

    int[] a3 = new int[2][3];

    System.out.println(a1.getClass() == a2.getClass());//结果为true.

    System.out.println(a1.getClass() == a3.getClass());//结果为false.

    System.out.println(al.getClass().getSuperclass().getName());//获取父类名,是Object.

    System.out.println(a3.getClass().getSuperclass().getName());//获取父类名,是Object

数组反射的应用:

    Array工具类用于完成对数组的反射操作,该类供了动态创建和访问 Java 数组的方法。

    我们可以用Array来对数组的内容进行设置和获取。

       public static void printObject(Object obj){

       Class clazz = obj.getClass();

       //是数组就遍历,不是就打印对象。

        if(clazz.isArray()){

           int len = Array.getLength(obj);

           for(int i=0;i<len;i++){

              System.out.println(Array.get(obj,i));

           }

       }else{

           System.out.println(obj);

       }

       }

    List asList(T... a);jdk1.5后的参数。

    List aslist(Object o);jdk1.4的方法。

 

代码示例:

获构造器,并根据相应的构造器创建对象。

publicclass GetConstructorDemo2 {

    publicstaticvoid main(String[] args)throws Exception {

       //获取字节码文件并加载进内存。

       String className = "cn.itcast.bean.Person";

       Class clazz = Class.forName(className);

       getConstructor_1(clazz);

       getConstructor_2(clazz);

    }

    //根据空参数的构造方法创建对象。

    publicstaticvoid getConstructor_1(Class clazz)throws Exception{

       Object obj = clazz.newInstance();

       System.out.println(obj);

    }

    //根据带参数nameage的构造器创建对象。

    publicstaticvoidgetConstructor_2(Class clazz) throws Exception{

       //获取构造器。

       Constructorconstructor =clazz.getConstructor(String.class,int.class);//明确参数类型。

       Person p = (Person)constructor.newInstance("list",23);//创建对象并并传实参。

    //因为不知道是根据哪个对象的构造方法创建的对象,所以创建的对象的类型是Object的,需要强转。

       p.setAge(55);//自己写的Person中的方法设置值。

       p.getAge();//获取值。

       System.out.println(p);

      

    }

}

获取字段对象,获取age字段值,并设置值和获取值。

publicclass GetFieldDemo3 {

    publicstaticvoid main(String[] args)throws Exception {

       String className = "cn.itcast.bean.Person";

       Class clazz = Class.forName(className);

       getField(clazz);

//     getFields(clazz);

    }

    publicstaticvoid getField(Class clazz)throws Exception{

       Object obj = clazz.newInstance();

//     Field ageField = clazz.getField("age");

       Field ageField = clazz.getDeclaredField("age");//获取似有age字段对象。

       //暴力访问。

       ageField.setAccessible(true);

      

       ageField.set(obj, 23);

       Object o = ageField.get(obj);

       System.out.println(o);

    }

    //获取所有Field对象。

    publicstaticvoid getFields(Class clazz)throws Exception{

       Object obj = clazz.newInstance();

       Field[] fiels = clazz.getFields();

       for(Field f : fiels){

           System.out.println(f);

       }      

    }

}

获取Method对象,并掉用各个方法。(空参数,带参数,静态)

publicclass GetMethodDemo4 {

    publicstaticvoid main(String[] args)throws Exception {

       String className = "cn.itcast.bean.Person";

       Class clazz = Class.forName(className);

       getMethod_1(clazz);

       getMethod_2(clazz);

       getMethod_3(clazz);

    }  

    //获取空参数的Method对象,并调用空参数的方法。

    publicstaticvoid getMethod_1(Class clazz)throws Exception{

       Object obj = clazz.newInstance();

       Method method = clazz.getMethod("method",null);//获取method空参数的方法。

       method.invoke(obj, null);

    }

    //获取带参数的Method对象,调用方法,并传实参。

    publicstaticvoid getMethod_2(Class clazz)throws Exception{

       Constructor constructor =clazz.getConstructor(String.class,int.class);

       Object obj = clazz.newInstance();

       Method method = clazz.getMethod("method", String.class,int.class);//明确方法名,参数。

       method.invoke(obj, "小强",32);

    }

    //获取静态空参数Method对象,并调用静态方法。

    publicstaticvoid getMethod_3(Class clazz)throws Exception{

       //调用静态方法不用创建对象。

       Method method = clazz.getMethod("staticMethod",null);

       method.invoke(null,null); 

    }

}

数组的反射

publicclass ArrayReflectDemo {

    publicstaticvoid main(String[] args) {

       int[] a1 =newint[]{5,6,7};

       int[]a2 =newint[4];

       int[][] a3 =newint[2][3];

       String[] a4 = new String[]{"a","b","c"};

      

       //父类引用接收子类对象。

       Object obj1 = a1;//可以接收。

       Object obj2 = a4;

//     Object[] obj3 = a1;//不行。编译会出错。

       Object[] obj4 = a3;

       Object[] obj5 = a4;

       System.out.println(Arrays.asList(a1));//asList(T... a)使用的是jdk1.5版本来接收参数。将参数当成一个对象。

       System.out.println(Arrays.asList(a4));//asList(Object[] o)使用的是jdk1.4版本的方法。将参数当成一个数组,以可以打印出所有元素。

    }

代码演示:

读取配置文件:利用反射来创建容器对象。将容器在api中的目录,存放到配置文件中,然后读取配置文件。

publicclass ReflectTest {

publicstaticvoid main(String[] args)throws Exception {

//     Collection coll = new ArrayList();

       //第一种读取配置文件方式:加载config.Properties文件。用流来读取。(这种方式即可读,也可以写到硬盘上保存)

//     InputStream ips = new FileInputStream("config.properties");

       //第二种读取方式:用类加载器来加载配置文件。

//     InputStream ips = ReflectTest.class.getClassLoader().getResourceAsStream("cn/itcast/p4/test/config.properties");//使用的是类加载器中的方法。相当于在在classPath指定的跟目录下逐个查找config文件。

       InputStream ips = ReflectTest.class.getResourceAsStream("config.properties");//相对于ReflecTest文件所在包下的目录config.properties

       //config.properties相当于classPath的跟目录。

//创建一个properties容器。

Properties props = new Properties();

//将流中的数据读取到容器中。

       props.load(ips);

       ips.close();

       String className = props.getProperty("className1");

       Collection coll = (Collection)Class.forName(className).newInstance();

//     Collection<ReflectPoint>coll = new HashSet<ReflectPoint>();

ReflectPoint pt1 = new ReflectPoint(3,3);

       ReflectPoint pt2 = new ReflectPoint(4,4);

       ReflectPoint pt3 = new ReflectPoint(5,5);

       ReflectPoint pt4 = new ReflectPoint(3,3);

      

       coll.add(pt1);

       coll.add(pt2);

       coll.add(pt3);

       coll.add(pt4);

       System.out.println(coll.size());

    }

}

 
http://edu.csdn.net/heima android培训 http://edu.csdn.net/heima ; java培训期待与您交流!详细请查看http://edu.csdn.net/heima

原创粉丝点击