张孝祥高薪技术2:反射的特性

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

反射
   1 Class: Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.
   2 字节码:一个类被类加载到内存中,占用一片存储空间,就个空间就是字节码.
   3 得到字节码: 类名.class      对象.getClass()   Class.forName("类名")
     代码验证
                String str = "abc";
  Class c1 = str.getClass()//得到字节码;
  Class c2 =String.class;//得到字节码
  Class c3 =Class.forName("java.lang.String");//得到字节码
  c1==c2==c3
  System.out.println(c1.isPrimitive());//不是基本类型
  System.out.println(int.class.isPrimitive());//基本类型
  System.out.println(int.class==Integer.class);//两种不同类型的字节码
  System.out.println(int.class==Integer.TYPE);//同类型的字节码
  System.out.println(int [].class.isPrimitive());//数组不是原始类型
  /*属于基本类型:原始类型的字节码
  Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE,
  Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE*/
  4 反射就是把Java类中的各种成分映射成相应的java类。
  5 Constructor类
                //得到某个类所有的构造方法
  Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
  //得到某个类的一个构造方法
  Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
                //由构造方法得到类的对象,必须是相对应的参数:new StringBuffer("sdf")
  String Str = (String)constructor.newInstance(new StringBuffer("sdf"));
  Class.newInstance()方法:
       例子:String obj = (String)Class.forName("java.lang.String").newInstance();
  6 Field类代表某个类中的一个成员变量
    public Field getField(String name)  这个name必须是这个类的成员变量(非私有)的名字,如类的 int x=8,x就是name中的一个                 getDeclaredField则可以访问所有的成员变量
   要想访问  则先用setAccessible(true)方法
                                           filex.setAccessible(true);
                             System.out.println(filex.get(pt1));

 
  7 成员变量反射的综合应用
   //o是一个类的实例对象 
 private static void changeStringValue(Object o) throws Exception
 {
  // TODO Auto-generated method stub
  //由对象找到字节码
  Class c1 = o.getClass();
  //由字节码 找出所有的成员类型
  Field [] file = c1.getFields();
  //判断成员类型
  for(int i=0;i<file.length;i++)
  {
   if(file[i].getType()==String.class)
   {
    //由对象找到成员类型变量
    String ago = (String)file[i].get(o);
    //新字符代替旧字符
    String now = ago.replace("b", "a");
    //装进去
    file[i].set(o, now);
      
   }
   
  }
  System.out.println(o);//打印的toString()方法已经被重写
  
 }

  8 Method类代表某个类中的一个成员方法
   String str ="abc";
  获得字节码
  Class c = str.getClass();
  获得 方法
  Method charAt = c.getMethod("charAt", int.class);
         调用方法
  System.out.println(charAt.invoke(str, 2));
  new Object[]{1}:表示一个存储 new Object 对象的数组,现在里面有一个元素,1自动装箱为Intger型
  System.out.println(charAt.invoke(str, new Object[]{1}));
   如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
 9 用反射方式执行某个类中的main方法
   问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
   解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

 10 数组的反射及应用
a、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

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

c、基本类型的一维数组可以被当作Objcet类型使用,不能当作Object[]类型使用。
;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用
d、Arrays.asList()方法处理int[]和String[]时,有差异。

e、Array工具类用于完成对数组的反射操作

f、怎么得到数组元素的类型

无法得到数组的类型,但可以得到数组元素的类型

int [] a = new int [3];

Object[] a = new Object[]{“a”,1};

a[0].getClass().getName(); //这里可以得到某个元素的类型

注意代码注释部为什么不能通过编译:下有无法通过图

import java.lang.reflect.Array; 
 
import java.util.Arrays; 
 
public class ArrayOfReflect { 
 
    public static void main(String[] args) { 
 
       int [] a1 = new int[]{1,2,3}; 
 
       int [] a2 = new int[4]; 
 
       int[][] a3 = new int [2][3]; 
 
       String[] a4 = new String[]{"a", "b", "c"}; 
 
       System.out.println(a1.getClass() == a2.getClass()); 
 
       /*
 
        * 所有类型相同和维数相同的数组它的的类字节码都是一样的
 
        * a1的类字节码 与a3、a4的类字节码永远都不会一样
 
        * jdk1.5以后,编译器认为这2个类型是不一样的。
 
        * 根本没有比较的需要。对于总是不成立的比较,其实是没有意义的
 
        * 所以编译器会报错! 
 
       System.out.println(a1.getClass() == a4.getClass());
 
       System.out.println(a1.getClass() == a3.getClass());
 
       */ 
 
       System.out.println(a1.getClass().getName()); 
 
       System.out.println(a1.getClass().getSuperclass().getName()); 
 
       System.out.println(a4.getClass().getSuperclass().getName()); 
 
       Object aObj1 = a1; 
 
       Object aObj2 = a4; 
 
//     Object[] aObj3 = a1;  
 
       Object[] aObj4 = a3; 
 
       Object[] aObj5 = a4; 
 
       System.out.println(a1); 
 
       System.out.println(a4); 
 
       System.out.println(Arrays.asList(a1)); 
 
//     注意这里为什么不能打印出a1里的值,为了兼容jdk1.4,但jdk1.4只能传Object[]  
 
//     但a1是基本数据类型,无法打印出里面的值,那怎样解决呢  下面通过自己编写方法,来打印  
 
       System.out.println(Arrays.asList(a4)); 
 
        printObject(a1); 
 
    } 
 
    private 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.print(Array.get(obj, i)); 
 
           } 
 
       } else { 
 
           System.out.println(obj); 
 
       } 
 
    } 
 

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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值