黑马程序员-反射

来源:互联网 发布:小幽灵网络论坛 编辑:程序博客网 时间:2024/05/29 15:26
---------------------- android培训、java培训、期待与您交流! ----------------------

导入类中的静态方法:import java...*

反射:

    (.class文件并不是类的字节码,只有当类加载器将其加载如内存后的二进制代码才是字节码,没有公共的构造方法,由类加载器的defineClass自动构造)

    1)   涉及的的类:

          1. java.lang Class<T>

          2. java.lang.reflect Array

          3. java.lang.reflect Method

         4.  java.lang.reflect Constructor<T>T为指定构造方法所属的类

         5.  java.lang.reflect Field

    2)   类是对象的抽象,每个类在内存中只有一份二进制字节码文件,Class类是所有类和类型的二进制字节码文件的抽象。

      获取Class类对象的方式:

         1.     通过类.class获得

         2.    通过实例变量.getClass()方法获取

         3.    通过Class类的静态方法Class.forName(“包.类名”)获得:其中如果已经加载过该类的字节码文件时,在虚拟机中找到返回它,如果没有,用类加载器加载字节码,并缓存在虚拟机中,返回字节码

    3)   基本数据类型有自己的字节码,包装类的TYPE和基本数据类型的字节码相同:

      如int.classInteger.class不是同一份字节码。

       int.class Integer..TYPE相同

    4)   数组与Object的关系及其反射:

       所有数组都是Object类的子类

       同一数据类型具有相同维度的数组对象,它们的Class是相同的,如:

       int[] a =new int[3]int [] b = new int[5]a.getClass()b.getClass()相等。

       基本数据类型不是Object类的子类,所以 Object[] obj = new int[2];编译不通过。

      Object数组中存放的必须是Object类的子类对象。

       数组转集合时,会将基本数据类型的数组转换为一个元素对象存放在集合中。而其他类型的数组会将每个数组元素作为单独的一个元素对象存放在集合中。

      数组反射:

      获取数组的长度和访问数组中的元素:

              通过java.lang.reflect.Array类完成,直接调用其中的方法即可。

    5)   通过类的字节码进行反射:

          (1).构造方法(Constuctor)反射:

            1.获得所有构造方法:

            Constructor<?>[]getConstructors()返回一个包含某些 Constructor对象的数组,这些对象反映此 Class对象所表示的类的所有公共构造方法。

           2.获得一个构造方法:

           Constructor<T>getConstructor(Class<?>... parameterTypes)  返回一个 Constructor对象,它反映此 Class对象所表示的类的指定公共构造方法。

应用:

通过获得一个构造方法,使用这个构造方法的newInstance(Class<T>… arg)获得该类的实例对象。当使用的构造函数是无参构造函数时,可直接调用Class.newInstance()方法。使用一个无参的构造方法实例化对象,并将该对象缓存起来,以便下次调用。因为使用反射影响程序性能。

注意:

获取一个构造方法传入参数的类型的字节码要和使用该构造方法传入的参数类型一致。不然运行时会抛出非法参数异常

     (2).成员变量(Field)反射:

          1.获得所有公共(public修饰的)成员字段:

          Field[] getFields()返回一个包含某些 Field对象的数组,这些对象反映此 Class对象所表示的类或接口的所有可访问公共字段。

    2.获得一个公共成员字段:

         Field getField(Stringname)返回一个 Field对象,它反映此 Class对象所表示的类或接口的指定公共成员字段。

    3.获取所有成员变量字段:

        Field[]getDeclaredFields()返回 Field对象的一个数组,这些对象反映此 Class对象所表示的类或接口所声明的所有字段

    4.获取一个成员变量字段:

       FieldgetDeclaredField(String name)返回一个 Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。

访问某个该类对象的变量的值:

    通过Field类的:

    Objectget(Object obj)返回指定对象上此 Field表示的字段的值。当该Field对象是private修饰时抛出异常,调用该方法前必须设置该Field对象的accessible标志:public void setAccessible(boolean flag) throws SecurityException

将此对象的 accessible标志设置为指示的布尔值。值为 true则指示反射的对象在使用时应该取消 Java语言访问检查。值为false则指示反射的对象应该实施Java语言访问检查。

成员反射案列:通过改变对象成员变量的值 

    (3).成员方法(Method)的反射:

          1.获得所有公共成员方法:

            Method[]getMethods()返回一个包含某些Method对象的数组,这些对象反映此Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member方法。

         2.获得一个公共成员方法:

           MethodgetMethod(String name, Class<?>... parameterTypes)  返回一个 Method对象,它反映此 Class对象所表示的类或接口的指定公共成员方法。

         3.获得所有成员方法:

          Method[]getDeclaredMethods()返回 Method对象的一个数组,这些对象反映此 Class对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

         4.获得一个成员方法:

         MethodgetDeclaredMethod(String name, Class<?>... parameterTypes)返回一个 Method对象,该对象反映此 Class对象所表示的类或接口的指定已声明方法。

应用:

     通过在Method类对象上调用invoke方法,将Method类实例所表示方法作用于该方法所属类的对象:

     Objectinvoke(Object obj, Object... args)其中obj表示方法所属类的对象,当objnull时,该方法为静态方法args,表示方法需要的参数对带有指定参数的指定对象调用由此 Method对象表示的底层方法。

注意:

       当方法的参数为数组时,通过反射调用方法时,传入的数组会被当成是多个参数,抛出非法参数异常。这时需要将数组封装为Object类的对象:

        new Object(){new String[]{“arg1”,”arg2”,”arg3”}}

       (Object)new String[]{“arg1”,”arg2”,”arg3”}

练习:

package org.cc.reflect;

/*
 * 反射调用类的公共成员方法和私有方法
 *
 */
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;

public class RMethodDemo {
 public static void main(String[] args) throws Exception {
  Class cla1 = Class.forName("org.cc.reflect.Student");
  Constructor<Student> cons = cla1
    .getConstructor(String.class, int.class);
  Student stu = (Student) cons.newInstance("chenchao", 21);
  Field field1 = cla1.getDeclaredField("name");
  field1.setAccessible(true);
  String name = (String) field1.get(stu);
  field1.set(stu, "ch");

  // 公共成员方法反射调用
  Method method = cla1.getMethod("print", null);// 获得公共方法
  System.out.println(method.invoke(stu, null));// 调用公共方法

  // 私有成员方法反射调用
  Method method2 = cla1.getDeclaredMethod("setName", String.class);// 获得私有成员方法
  method2.setAccessible(true);// 设置私有成员方法访问时忽略java安全检查
  method2.invoke(stu, "chch");// 调用私有成员方法

  System.out.println(field1.get(stu));

 }
}

class Student {
 private String name;
 private int age;

 public Student(String name, int age) {
  this.setName(name);
  this.setAge(age);
 }

 private void setName(String name) {
  this.name = name;
 }

 private String getName() {
  return this.name;
 }

 private void setAge(int age) {
  this.age = age;
 }

 private int getAge() {
  return this.age;
 }

 public String print() {
  return this.name + " " + this.age;
 }
}

---------------------- android培训、java培训、期待与您交流! ----------------------

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

原创粉丝点击