Java——反射概念、应用

来源:互联网 发布:淘宝卖家骗好评 投诉 编辑:程序博客网 时间:2024/04/30 21:30

17_透彻分析反射的基础_Class类

  Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class

  如何得到各个类的字节码,即Class类?

  1、类名.class //直接使用类.class获得

  2、对象.getClass()//通过对象调用其getClass方法

  3、Class.forName(“java.util.Date”) //使用类加载器加载

  Java原始基本类型:booleanbytecharshortintlongfloat,double 和关键词 void同样都有Class类,通过.class可获得他们的类字节码

18_理解反射的概念

  反射就是吧Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就想七成是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

  一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。

19_构造方法的反射应用  

  Constructor 类,各种类的构造方法的反射类。

  Constructor 反射类对象的获得:

  例:Constructor constructor=String.class.getConstructor(StringBuffer.class);

  构造方法可以用于构造实例对象

  String str=(String)constructor.newInstance(new StringBuffer("abc"));

  Class本身也还有newInstance方法,可以直接调用,例如

  String obj=(String)String.class.newInstance();

  //类似于调用无参的构造方法。

20_成员变量的反射

  Field 类,类中成员变量的反射类。

  Field 对象的反射获得:

  class Person
  {
    public String personname;
    protected String personcity;
    private String personadd;
    public int personage;
    public Person(String personname, String personcity, String personadd)
    {
      this.personname = personname;
      this.personcity = personcity;
      this.personadd = personadd;
      this.personage=0;
    }
  }

  ...... 

  //一下为Field反射类的应用部分

  ...... 

  Person person=new Person("myname","mycity","myaddress");

  Field fieldname=person.getClass.getField("personname");//基本方式获得public成员变量

  Field fieldcity=person.getClass.getDeclaredField("personcity");//获得声明的成员变量

  Field fieldadd=person.getClass.getDeclaredField("personadd");//获得声明的成员变量

  //Field[] fields=person.getClass.getDeclaredFields();//获得声明的所有成员变量数组  

  System.out.println("personname:" + fieldname.get(person));//打印成员变量的值

  System.out.println("personcity:" + fieldcity.get(person));//protect修饰变量可直接读取

  personadd.setAccessible(true);//设置成员变量可访问,包括private成员变量(暴力反射)

  System.out.println("personcity:" + fieldadd.get(person));//private成员必须设置访问权限setAccessible(true)后才可以访问

  成员变量的修饰符public、protect、private对反射类有不同的权限要求,注意红色字体部分。

21_成员变量反射的综合案例

  循环访问类示例对象的成员变量,并修改其变量值:

  public class Java_Test  //声明运行主体类
  {

    public Java_Test()
    {
      // TODO Auto-generated constructor stub
    }
    public static void main(String[] args) throws Exception
    {
      System.out.println("-------------------------------");
      Person person=new Person("myname","mycity","myaddress");
      System.out.println(person.toString());  //打印原始对象成员变量的值
      System.out.println("-------------------------------");
      chageFields(person);  //调用方法访问并修改类成员变量的值
      System.out.println(person.toString());  //打印修改后的成员变量值
      System.out.println("-------------------------------");
    }
    public static void chageFields(Object obj) throws IllegalAccessException
    {
      String str;
      Field[] fields=obj.getClass().getDeclaredFields();  //获得成员变量反射类对象数组
      for(Field field:fields)  //循环访问数组成员
      {
        field.setAccessible(true);  //设置成员变量可访问(暴力反射)
        if(field.getType()==String.class)
        {
          str=(String)field.get(obj);  //读取成员变量的值
          str=str.replace('_',' ');  //修改
          field.set(obj,str);  //重新设置成员变量的值
        }
      }
    }

  }

  class Person  //声明要操作的类
  {
    public String personname;
    protected String personcity;
    private String personadd;
    public int personage;
    public Person(String personname, String personcity, String personadd)
    {
      this.personname = personname;
      this.personcity = personcity;
      this.personadd = personadd;
      this.personage=0;
    }

    @Override  //覆盖toString方法,显示成员变量的值
    public String toString()
    {
      return "personname:" + personname +"\npersoncity:"+personcity + "\npersonadd:" + personadd;
    }

  }

22_成员方法的反射  

  Method 类,类中各个成员方法的反射类

  成员方法的反射应用方法:先得到类字节码的方法,然后再指定在哪个对象上调用方法,最后进行调用。

  例如:利用反射调用String类的charAt方法

  String str=new String("abc")

  Method methodCharAt=String.class.getMethod("charAt",int.class);

  //注意参数类型及意义:类字节码class.getMethod(“方法名”,方法参数类型.class)

  System.out.println(methodCharAt.invoke(str,1));  //方法对象.invoke(原对象,参数对象数组)

  输出结果同直接调用对象方法,即:str.charAt(1)

  *注意* 静态方法的反射调用可以写成:方法对象method.invoke(null,参数对象数组)

      无参静态方法反射调用要写成:方法对象method.invoke(null,null)

      JDK1.4版本注意参数类型构成:methodCharAt.invoke(str,new Object[]{1})

23_对接收数组参数的成员方法进行反射

  示例:调用其他类的main方法 public static void main(String[] args)

  String mainClassName=new String("MainClassName");
  Method mainMethod=Class.forName(mainClassName).getMethod("main", String[].class);
  mainMethod.invoke(null, new Object[]{new String[]{"Ling","Dong","Cao"}});
  mainMethod.invoke(null, (Object)new String[]{"Ling","Dong","Cao"});
  为兼容JDK1.4,invoke会将数组参数拆分为单个的元素来作为参数列表。在以上示例中如果直接使用数组作为参数,则会出现main方法参数个数错误:

  //错误的写法:mainMethod.invoke(null,new String[]{"Ling","Dong","Cao"});

24_数组与Object的关系及其反射类型
  1、具有相同维数和元素类型的数组属于统一个类型,即具有相同的Class实例对象

  2、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。

  3、基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本类型的一维数组既可以当做Object类型使用,又可以当做Object[]类型使用。

  示例:

  int[] num1=new int[3];

  int[] num2=new int[4];

  int[][] num12=new int[3][4];

  String[] str=new String[3];

  下面说明各个对象的反射类的关系

  num1.getClass()==num1.getClass()

  num1.getClass()!=num12.getClass()

  num1.getClass()!=str.getClass()

  数组与Object的关系:

  num1.getClass().getSuperClass().getName()==str.getClass().getSuperClass().getName()=="java.lang.Object"

  Object objint1=num1;

  Object objint12=num12;

  Object objstr=str;

  //Object[] objint=num1;  //错误的写法,int基本类型不是Object

  Object[] objint12=num12;  //正确写法,因其成员为int[],为Object。

  Object[] obj_str=str;  //正确,因为String实例即为Object对象类型

  Array.asList()方法处理int[]和String[]的差异。

  int[] num=new int[]{1,2,3};
  String[] str=new String[]{"aaa","bbb","ccc"};

  System.out.println(Arrays.asList(num1));  //打印输出类似“[[I@c17164]”的字符
  System.out.println(Arrays.asList(str));  //打印类似“[aaa, bbb, ccc]”的字符

25_数组的反射应用

  打印传入对象,如果为单一对象,直接打印,如果为数组,则逐一打印数组元素(对数组对象的判断应用)

  public void printObject(Object obj)
  {
     Class cla=obj.getClass();
     if(cla.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);
     }
  }

0 0
原创粉丝点击