java反射机制

老王:小王呀,听说你酒量不错

小王:酒量还行

老王:能喝多少

小王:白的可以喝一斤吧

老王:这酒量不错哦,看你酒量不错,那你就给我来讲一讲java的反射机制吧

小王:(懵逼中,我酒量不错和java的反射机制有什么关系)这个...........

老王:怎么了,酒量这么好java的反射机制都不知道?

小王:好吧

老王:你怎么理解反射的?反射有什么作用?

小王:我们不使用方式这种方式想获取某一个类的对象,我们只有通过new(new  类名())的方法得到该类的对象,使用反射我们可以不使用new(new  类名())的这种方式,从而创建类的对象,还可以调用该类的方法(包括私有方法)也可以获取或者设置该类的成员变量值(包括私有成员变量)

老王:反射第一步是干什么?

小王:先获取类的class对象

老王:如何获取呢?获取类的class对象有几种方式呢?

小王:三种方式,                                                                                                                                                                                               方式1:Class clazz  =  对象名.getClass();                                                                                                                                                       方式2:Class clazz = 类名.class;                                                                                                                                                                     方式3:Class  clazz = Class.forName(“类全名”);

老王:那你觉得哪一个方式比较好,比较常用呢?

小王:我本人觉得第三种方式比较好,也比较常用,                                                                                                                                                         评价:

                       方式一:既然我已经有该类的对象了,那我为什么还要通过发送来调用他的方法呢,为什么不直接调用呢?这种方式只有可以调用private修饰的方法。

                      方式二:如果你一个类的构造方法被private修饰的,那么方式一肯定是使用不了了,因为你不能直接创建该类的对象,只有通过暴力反射(暴力反射就是指调用该类私有的方法和属性)的方式去创建该类的对象, 所以可以使用第二种方式。

                     方式三:我觉得方式三功能最强大,我可以不知道该类的类名是什么就可以调用该类的方法和属性,很多框架中也是使用第三种方式,并且方式三比较灵活,我可以把全类名写在配置文件中,读取配置文件,获取全类名创建对象,这个是方式二和方式一都做不到的。             

老王: 那你能不能跟我讲一下框架中是如何使用这种反射呢?框架中的代码是别人已经写好的哦,他怎么知道你配置的那个类中有什么方法呢?也不知道你那个方法中有什么参数,方式调用方法是要传入方法名和参数类型的Class对象的哦。

小王:这个简单,框架中一般都需要你实现指定的接口,实现接口中的抽象方法,而接口是框架的开发者写的,他肯定知道方法名和参数类型是什么呀。

老王:你理论掌握还不错,那你可以用代码写一下吗?把常用的操作写出来。

小王:我可以明天写吗?现在已经下班了。

老王:年轻人别种急着下班,现在你还年轻,要努力学习,为以后技术做铺垫。

小王:沉默中..........

老王:那你现在就去写吧,写完给我看一下。

小王:努力敲码中.................................................

 

   反射中常用的方法  


        // 获得Class对象
        Class<Student> c = Student.class;
        // 获得类名字符串
        System.out.println(c.getSimpleName());
        // 获得类全名字符串
        System.out.println(c.getName());
 

 通过去反射调用构造方法创建对象

/*
       反射操作public修饰的构造方法
    */
    @Test
    public void test01()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得两个参数构造方法对象    里面的参数为,你调用的构造方法里面需要参数类型的Class对象
        Constructor conn = c.getConstructor(String.class, int.class);
        // 根据参数创建学生对象
        Object stu02 =  conn.newInstance("老王",20);
        System.out.println(stu02);
    }


    /*
        反射操作private修饰的构造方法
     */
    @Test
    public void test02()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得一个参数构造方法对象
        Constructor con = c.getDeclaredConstructor(String.class);
        // 暴力反射(设置取消权限检查)
        con.setAccessible(true);
        // 创建对象
        Object stu = con.newInstance("老王");
        System.out.println(stu);
    }


    /*
        反射之获得所有构造方法对象
     */
    @Test
    public void test03()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得所有构造方法对象:只能获得public修饰的
        // Constructor[] cons = c.getConstructors();
        // 获得所有构造方法对象:包括private修饰的
        Constructor[] cons = c.getDeclaredConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }
    }

    

小王:王哥写好了,给您

老王:(认真的看了看)你这个好像没有写完呀,还有通过反射调用方法和通过反射给变量赋值和获取变量的值。

小王:我觉得他们和使用方式调用构造方法都差不多我就没有写了,方式调用构造方法使用  Constructor  类,反射调用方法使用  Method 类,方式操作变量使用  Field  对象,其余的都没有什么改变。

老王:照你这样说月薪3k和月薪2K也差不多咯?(露出了猥琐的笑容)               

小王:(马上跑到电脑面前开始敲码中.............................)

反射调用方法

/*
        反射操作public修饰的成员方法
     */
    @Test
    public void test01()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 创建学生对象
        Object stu = c.newInstance();
        // 获得有参数的study方法对应Method对象
        Method studyMethod02 = c.getMethod("study",int.class);
        // 传递参数调用方法
        studyMethod02.invoke(stu,10);
    }


    /*
        反射操作private修饰的成员方法
     */
    @Test
    public void test02()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 创建学生对象
        Object stu = c.newInstance();
        // 获得sleep方法对应Method对象
        Method sleepMethod = c.getDeclaredMethod("sleep",String.class,int.class);
        // 暴力反射
        sleepMethod.setAccessible(true);
        // 调用方法
        sleepMethod.invoke(stu,"老王",8);

    }

    /*
        反射操作static修饰的成员方法
     */
    @Test
    public void test03()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得静态方法对应的Method对象
        Method drinkMethod = c.getDeclaredMethod("drink");
        // 暴力方式
        drinkMethod.setAccessible(true);
        // 调用方法
        drinkMethod.invoke(c);
    }


    /*
        反射之获得所有成员方法对象
     */
    @Test
    public void test04()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得类所有的成员方法对象,返回数组,只能获取public修饰的, 包括父类的
        // Method[] methods = c.getMethods();
        // 获得类所有的成员方法对象,返回数组,包括private修饰的,只包括本类的
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

      反射操作变量

/*
       反射操作public修饰的成员变量
    */
    @Test
    public void test01()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 创建学生对象
        Object obj = c.newInstance();
        System.out.println(obj);
        // 根据成员变量名获得field对象
        Field field01 = c.getField("gender");
        // 给obj对象的gender成员变量赋值
        field01.set(obj, "男");
        System.out.println(obj);
        // 获得对象obj的gender成员变量值
        Object result = field01.get(obj);
        System.out.println(result);
    }


    /*
        反射操作private修饰的成员变量
     */
    @Test
    public void test02()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 创建学生对象
        Object obj = c.newInstance();
        System.out.println(obj);
        // 根据成员变量名获得field对象
        Field ageField = c.getDeclaredField("age");
        // 暴力反射
        ageField.setAccessible(true);

        // 给obj对象的age成员变量赋值
        ageField.setInt(obj, 20);
        System.out.println(obj);
        // 获得对象obj的age成员变量值
        int result = ageField.getInt(obj);
        System.out.println(result);
    }


    /*
        反射之获得所有成员变量对象
     */
    @Test
    public void test03()throws Exception{
        // 获得Class对象
        Class c = Student.class;
        // 获得类所有的成员变量对象,只包括public修饰的
        // Field[] fields = c.getFields();

        // 获得类所有的成员变量对象,包括private修饰的
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }

                                                               

 小王:(高高兴兴的跑过去,感叹到终于可以下班了................)写好了,给我您

 老王:(认真的查看中..................)小王不错哦,继续努力,不要总想着下班,年轻人就该好好努力,下次我把我女儿介绍给你。

 小王:(猥琐的笑了一笑)我怕配不上你女儿。

  晚上12点.....................................

老王:小王还不下班呀!

小王:我又没有女朋友,这么早下班也没事干,所以还是好好努力工作比较好。

老王:哈哈哈哈哈哈哈哈哈哈

               

               

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值