反射

反射的基础是Class类
Class:

 JAVA类用于描述一类事物的共性。而是什么属性则是由类的实例对象来确定的,不同的实例对象有不同的属性值。

 Class则是用于描述JAVA类的共性的类,描述了类的名字,访问属性,包名,字段名称列表,方法名称列表等。

 Class的实例对象为某个类的字节码。
  获取字节码的实例对象方法有三种
  1. 类名.class  System.class
  2. 对象.getClass  new Date().getClass()
  3. Class.forName("类名") Class.forName("java.util.Date")
 

 Class cls1=Date.class //Date类的字节码 ,已经加载到内存
 Class cls2=p1.getClass();//调用对象的getClass()得到类的字节码
 Class.forName("java.lang.String") //返回该类字节码

反射就是把Java类中的各种成分映射成相应的Java类,如:一个Java类中用Class类的对象来表示,一个类中组成的部分:
成员变量,方法,构造方法,包等信息,也是用一个个Java类来表示的

 Class代表一份类字节码

 Method 类的实例对象代表 类的方法

Constructor类
 Constructor类代表类中的一个构造方法

 //获取某个类的所有构造方法
 Constructor[] constructors=Class.forName("java.lang.String").getConstructors();

 //获取某个构造方法,要用的参数类型 如:String(StringBuffer buffer)
 Constructor constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);

创建实例对象
 通常方法:String str=new String(new StringBuffer("abcd"));
   //Constructor类的 newInstance() 方法
 反射方法:String str=(String)constructor.newInstance(new StringBuffer("abc"))

Field类,代表某个类的属性
  Field fieldy=pt1.getClass().getField("y");  得出的是类的属性,值是不固定的,根据对象来确定
  fieldy.get(pt1);

  改field需要调用fieldy.set(obj,value);

Method类
 getMethod(name,parameterytpes) //类名,方法参数类型

 //执行方法用invoke(obj,parameters)
 Method methodCharAt=String.class.getMethod("charAt",int.class)
 //静态方法 name=null
 methodCharAt.invoke(str1,1);

 

 1  // 创建一个测试反射的类
 2  public   class  ReflectPoint {
 3       private   int  x;
 4       public   int  y;
 5       public  String str1 = " china " ;
 6       public  String str2 = " basketbool " ;
 7       public  String str3 = " itcast " ;
 8       public  ReflectPoint( int  x,  int  y) {
 9           super ();
10           this .x  =  x;
11           this .y  =  y;
12      }
13      
14  }
15 


 

  1  // 反射测试
  2  import  java.lang.reflect. * ;
  3  public   class  ReflectTest {
  4 
  5       /** 反射基本知识
  6       * 
  7       * 反射就是把java类中的各个成分映射为java类
  8       * 反射的基础是Class类,它是java类的描述类,Class类的实例是某个类的字节码
  9       *  @param  args
 10        */
 11       public   static   void  main(String[] args)  throws  Exception {
 12           //  TODO Auto-generated method stub
 13           // Class测试
 14           // Class的实例是类的字节码
 15          String str1 = " abcde " ;
 16          
 17           // 获取Class实例的三种方式
 18          Class cls1 =  str1.getClass();  // 获取该对象类的字节码
 19          Class cls2 = String. class ;   // 直接调用类的字节码
 20          Class cls3 = Class.forName( " java.lang.String " ); // 根据类名获取字节码
 21          
 22          System.out.println(cls1 == cls2);                     // true
 23          System.out.println(cls1 == cls3);                     // true
 24          
 25           // isPrimitive()是否是基本数据类型的字节码 8种+void
 26          System.out.println(cls1.isPrimitive());          // false
 27          System.out.println(Integer. class .isPrimitive()); // false
 28          System.out.println( int . class .isPrimitive());     // true
 29          
 30           // Integer.TYPE常量 代表包装的基本类型 的 字节码
 31          System.out.println( int . class == Integer.TYPE);      // true
 32          
 33           // 数组不是基本数据类型,是对象
 34          System.out.println( int []. class .isPrimitive());      // false
 35          System.out.println( int []. class .isArray());        // true
 36          
 37           // 得到String类的 String(StringBuffer)构造方法
 38          Constructor constructor = String. class .getConstructor(StringBuffer. class );
 39           // 可以构造方法,创建实例 ,并进行类型转换
 40          String str2  =  (String)constructor.newInstance( new  StringBuffer( " abcsd " ));
 41          
 42          ReflectPoint pt1 = new  ReflectPoint( 3 , 5 );
 43          
 44           // Field类
 45          Field fieldy = pt1.getClass().getField( " y " );
 46           // fieldy的值是5吗? 不是,fieldy不代表具体的值,只代表类的y变量
 47           // 因为取的是类的字节码,类中变量的值是根据 对象来决定的
 48           // 通过.get(object) 来获取某个对象的值
 49          System.out.println(fieldy.get(pt1));
 50          
 51          Field fieldx = pt1.getClass().getDeclaredField( " x " ); // 获取声明过的属性
 52          fieldx.setAccessible( true );  // 访问权限设置为true
 53          System.out.println(fieldx.get(pt1)); 
 54          
 55          changeString(pt1);
 56          System.out.println(pt1.str1);
 57          System.out.println(pt1.str2);
 58          System.out.println(pt1.str3);
 59          
 60           // Method
 61           // 取得类字节码 中的charAt方法
 62          Method methodCharAt = String. class .getMethod( " charAt " int . class );
 63           // 调用invoke(obj,parameter) 执行方法
 64          System.out.println(methodCharAt.invoke(str1, 1 ));
 65          
 66          
 67           // 调用main()方法,普通方式
 68           //  TestArguments.main(new String[]{"abc","1111"});
 69           // 使用反射调用,为了解决,给定类名,而不知道实现代码的情况下用
 70           // 从类字节码 得到 main方法
 71          Method methodmain = Class.forName(args[ 0 ]).getMethod( " main " ,String[]. class );
 72          methodmain.invoke( null , new  Object[]{ new  String[]{ " abc " , " 1111 " }});
 73          
 74           // 数组的反射
 75           int [] a1 = new   int [ 3 ];
 76           int [] a2 = new   int [ 4 ];
 77           int [][] a3 = new   int [ 2 ][ 3 ];
 78          String[] a4 = new  String[ 2 ];
 79           // 数组的字节码比较,看的是数组类型和数组维度
 80          System.out.println(a1.getClass() == a2.getClass());  // true  
 81          System.out.println(a1.getClass() == a3.getClass());  // false
 82          System.out.println(a1.getClass() == a4.getClass());  // false
 83          System.out.println(a3.getClass() == a4.getClass());  // false
 84           // 获取父类
 85          System.out.println(a1.getClass().getName());
 86          System.out.println(a1.getClass().getSuperclass().getName());
 87          System.out.println(a4.getClass().getSuperclass().getName());
 88           // 得出父类都是Object类
 89          Object aobj1 = a1;
 90          Object aobj2 = a2;
 91          Object aobj4 = a4;
 92           // Object[] aobj5=a1;  // 里面装的是基本类型,基本类型不是对象,不能装入
 93          Object[] aobj5 = a3;
 94          
 95           int [] t1 = new   int []{ 12 , 34 , 2 };
 96          printObject(t1);  // 打印对象,数组是对象,但t1数组元素是基本类型
 97          printObject( " xyz " );  // 打印对象
 98                              
 99      }
100 
101       private   static   void  printObject(Object obj){
102          Class clazz = obj.getClass();  // 获取该对象类的字节码
103           if (clazz.isArray()){
104               // Array是数组的反射类
105               for ( int  i = 0 ;i < Array.getLength(obj);i ++ ){
106                  System.out.println(Array.get(obj, i));
107              }
108          } else {
109              System.out.println(obj);
110          }
111      } 
112      
113       private   static   void  changeString(Object obj){
114          Field[] fields = obj.getClass().getFields();
115           for (Field field:fields){
116               if (field.getType() == String. class ){ // 同一份字节码 用==
117                   try  {
118                      String newValue = ((String)field.get(obj)).replace( ' a ' ' b ' );
119                      field.set(obj, newValue);
120                  }  catch  (Exception e) {
121                       //  TODO: handle exception
122                  }
123              }
124          }
125      }
126  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值