黑马程序员技术交流社区

标题: 【南京校区】反射的妙用(一) [打印本页]

作者: 大蓝鲸Java    时间: 2018-6-22 12:21
标题: 【南京校区】反射的妙用(一)
【南京校区】反射的妙用


    反射作为一个高薪技术,在框架的底层大量的使用,反射会根据一个字节码文件直接创建出该类的对象。

    即:你给我传递一个类名或者你给我传递一个字节码文件对象,我就可以创建出这个类的对象了。

   所以反射是我们高薪比不可少学习的东西。



(一)
反射或者字节码文件对象的三种方式

   
字节码文件获取的三种方式


1.        对象名.getCalss();                
2.        类名.class                       
3.        Class.forName("全类名");       




代码示例:
        1.通过对象获取
               
[AppleScript] 纯文本查看 复制代码
Student s = new Student();
                s.getClass()
                //getClass() 方法是在哪个类中的?Object
                //为咩这个方法要定义在Object类里面?
                //因为所有的类都有字节码文件,我们要写在所有的类共同的父类中.(向上抽取)
                //因为Object是所有的类直接父类或者间接父类,写在Object中,所有的类都可以用这个方法了
               


       
        2,通过类名.class调用
                Student.class


        3,Class 类中的一个静态方法获取
                Class.forName("全类名");//全类名:包名 + 类名






以上这三种方法,你觉得那种较为灵活,为咩?
        因为第一种和第二种,如果我们想要获取另外类的class对象.
        此时得去修改代码.


        因为第三种,我们可以把全类名写在本地的文本文件中
        然后用IO流,读这一整行. BufferedReader 因为有一个 readLine()
        这个方法的返回值line就是读到的全类名
        这样我们可以和第三种方式这样去结合
        Class.forName(line);




       
[AppleScript] 纯文本查看 复制代码
BufferedReader br = new BufferedReader(new File.......)
        Stbr.ring line = eadLine();
        Class.forName(line);
        此时我们一开始想要获取的是Student.然后第二次我们想要获取Person.
        1.不用到代码中修改代码了
        2,我们只需要修改文本文件中的那段话就可以了


(二)利用反射修改public属性值
Class clazz = Class.forName("com.heima.bean.Person");
先去获取这个类的字节码文件的对象
Constructor c = clazz.getConstructor(String.class,int.class);
获取有参构造        Person p = (Person) c.newInstance("张三",23);
通过有参构造创建对象
通过反射的方式得到Person的对象       
Field f = clazz.getField("name");
获取姓名字段的对象
f.set(p, "李四");
将上面创建的对象中的name赋值成"李四"


(三)利用反射修改非public属性值(暴力反射)
[AppleScript] 纯文本查看 复制代码
        Class clazz = Class.forName("com.heima.bean.Person");                        //先去获取这个类的字节码文件的对象
        Constructor c = clazz.getConstructor(String.class,int.class);        //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                                        //通过有参构造创建对象
        //通过反射的方式得到Person的对象
        Field f = clazz.getDeclaredField("name");                                                //暴力反射获取字段
        f.setAccessible(true);                                                                                        //去除私有权限
        f.set(p, "李四");       



(四)利用反射运行一个public修饰的方法
[AppleScript] 纯文本查看 复制代码
利用反射运行一个空参无返回值方法。

        Class clazz = Class.forName("com.heima.bean.Person");

        Constructor c = clazz.getConstructor(String.class,int.class);        //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                                        //通过有参构造创建对象       
       
        Method m = clazz.getMethod("eat");                                                                //获取eat方法
        m.invoke(p);                                                                                                        //运行这个方法
        //p.eat();//就相当于我们平时写的这样的效果。       


利用反射运行一个有参无返回值方法。
        Class clazz = Class.forName("com.heima.bean.Person");
       
        Constructor c = clazz.getConstructor(String.class,int.class);        //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                                        //通过有参构造创建对象       
       
        Method m2 = clazz.getMethod("eat", int.class);                                        //获取有参的eat方法
        m2.invoke(p, 10);                                                                                                //运行有参的eat方法



利用反射运行一个无参有返回值的方法
        Class clazz = Class.forName("com.heima.demo.Student");
               
        Constructor c = clazz.getConstructor(String.class,int.class);        //获取有参构造
        Student p = (Student) c.newInstance("张三",23);                                        //通过有参构造创建对象       
       
        Method m2 = clazz.getMethod("getName");                                                        //获取无参的getName方法
        String invoke = (String) m2.invoke(p);                                                        //运行无参的getName。该方法有返回值。
                                                                                                                                        //返回值是什么类型就可以强转成什么类型
        System.out.println(invoke);


利用反射运行一个有参有返回值的方法
        Class clazz = Class.forName("com.heima.demo.Student");
               
        Constructor c = clazz.getConstructor(String.class,int.class);        //获取有参构造
        Student p = (Student) c.newInstance("张三",23);                                        //通过有参构造创建对象       
       
        Method m2 = clazz.getMethod("eat",int.class);                                        //获取有参的eat方法
        int invoke = (int) m2.invoke(p,20);                                                                //运行有参的eat。该方法有返回值。
                                                                                                                                        //返回值是什么类型就可以强转成什么类型
        System.out.println(invoke);                       










欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2