反射

来源:互联网 发布:笔记本触摸屏校准软件 编辑:程序博客网 时间:2024/05/21 15:49
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1)      反射的理解

      运行时能自我检查,并能直接操作程序的内部属性。 Class 是所有类的通名,是所有java类的成分的映射成class类的过程。一下三种方式获得类的字节码。

         Class cls = String.class                           //  类名.class

        Class cls2 = new String().getclass                  //  对象.getclass

        Class cls3 = Class.forName(“java.lang.String”);     // 利用Class的静态函数

      Java 类的6个成分:   包、类名、方法、属性,父类、接口

2)      应用场景

      一个已经可以使用的应用程序,因为程序已经做好可以运行使用,不能再进行代码的加入了。而当后期我们新的功能加入程序时,该怎么做呢?就如我们的电脑一样,后期我们可能会鼠标、键盘等,所以电脑给我们预留了usb接口,只要符合这个接口规则的设备,电脑就可以通过加载驱动等操作来使用。

      那这个程序能用了,如何使用后期出现的功能类呢?

       常用的作法,会提供一个配置文件,来供以后实现此程序的类来扩展功能。对外提供配置文件,让后期出现的子类直接将类名字配置到配置文件中即可。该应用程序直接读取配置文件中的内容。并查找和给定名称相同的类文件。进行如下

                 ——加载这个类。

                 ——创建该类的对象。

                  ——调用该类中的内容。

应用程序使用的类不确定时,可以通过提供配置文件,让使用者将具体的子类存储到配置文件中。然后该程序通过反射技术,对指定的类进行内容的获取。

好处:反射技术大大提高了程序的扩展性。

 

3)      Class方法

           Class类中就包含属性有field(字段)、method(方法)、construction(构造函数)。的操作。

      注:

      字节码:类被加载到内存中,占据一定的存储空间,该空间的内容被称作该类的字节码。所以字节码实际上就是类文件的.class文件,包含以上java的六个成分的定义内容。
           

   九个预定义的Class:

         1)包括八种基本类型(byte、short、int、long、float、double、char、boolean)的字节码对象和一种返回值为void类型的void.class。

         2)Integer.TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示

  只要是在源程序中出现的类型都有各自的Class实例对象,如int[].class。数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型的。

Constructor<T>

getConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。

(1)(Class<?>... parameterTypes):  表示添加形参的字节码[类]。

e.g. Constructor con = String.class.getConstructor(string)

(2)利用Constructor对象,获得该类的对象

            String  P  =  (String)con.newInstance(”abc”)

//  普通方式: String  p = new String(”abc”);

(简化方式)  Constructor .newInstance() ----->Class.newInstance();

                 String str=(Stirng)Strign.class.newInstance(“abc”);


 Field

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

               Field  fieldage =  p.getclass.getField(age)     //getclass 是得到对象对应类的字节码。

                        //对于private 成员,getDeclareField 可以获得该对象,但是不可使用

               Field     fieldage    =  p.getclass.getDeclareField(age)

                            //要使上式可用,需要强制设置fieldage的可用

                       fieldage.setAcceeible(ture);

                          int age =  fieldage.get(p);

                            //  将对象中成员变量值进行修改

                     Field[] fields = p.getclass.getField();

                       for(field : fields ){

                               if ( field==String.class){

                                   String newvalue =field.get(p).replace(‘z’,’w’);

                                     field.set(newvalue)

                                 }

                         }

 Method

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

             主类调用其他类时,这些类向主类提供其名称参数 args[0]。

        获取某个类中的某个方法:(如Stringstr =”abc”)  

                Method[] getMethods();//只获取公共和父类中的方法。

                Method[]getDeclaredMethods();//获取本类中包含私有。

                Method  getMethod("方法名",参数.class(如果是空参可以写null));

                 Object invoke(Object obj,参数);//调用方法

             如果方法是静态,invoke方法中的对象参数可以为null。

           1)通常方式:str.charAt(1)

          2)反射方式:

           Method charAtMethod=Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

                                       charAtMethod.invoke(str,1);

 

       用反射方式执行某个main方法:

            public static void main(String[] args) throws Exception {  

                //普通方式  

                      Test.main(new String[]{"123","456","789"});  // Test

                      System.out.println("-----------------------------");  

                    //反射方式  

                      String className=args[0];  

                   Class clazz=Class.forName(className);  

                  

                     Method methodMain=clazz.getMethod("main",String[].class);  

                     //方式一:强制转换为超类Object,不用拆包  

                      methodMain.invoke(null, (Object)new String[]{"123","456","789"});  

                     //方式二:将数组打包,编译器拆包后就是一个String[]类型的整体 【只拆一次包】  

                       methodMain.invoke(null, new Object[]{new String[]{"123","456","789"}});  

     }  

 数组反射【数组是一个类】

             1、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I

             2、Object[]与String[]没有父子关系,Object与String有父子关系,所以newObject[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”}; Object x =“abc”能强制转换成Stringx =“abc”。

             3、如何得到某个数组中的某个元素的类型,

        例:

              inta = new int[3];Object[] obj=new Object[]{”ABC”,1};

        无法得到某个数组的具体类型,只能得到其中某个元素的类型,

        如:

              obj[0].getClass().getName()得到的是java.lang.String。

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

       Array.getLength(Object obj);//获取数组的长度

       Array.get(Object obj,int x);//获取数组中的元素

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



 


0 0
原创粉丝点击