java基础反射知识总结

作者: 开飞机的老舒克 | 来源:发表于2017-12-13 18:05 被阅读29次

    反射是什么?

    在运行状态中,获取一个类的所有属性和方法。这种动态获取信息以及调用对象的方法的功能。

    使用反射机制的一些框架?

    Retrofit中的注解功能、EventBus,动态生成框架 Gson。

    使用反射技术查看类信息

    获取Class对象的三种方法

    使用Object.getClass方法

    如果我们能知道一个对象,可以通过调用这个对象的getClass方法获得一个Class对象。
    例如:

    Person person = new Person();
    Class<? extends Person> aClass = person.getClass();
    System.out.println(aClass.getName());
    
    

    这时候就会打印这个对象的全包名,aClass中还有其他信息。

    使用.class方法
    Class<? extends Person> aClass = Person.class;
    System.out.println(aClass.getName());
    System.out.println(int.class);
    
    

    如果没有获取某个类的对象,无法使用getClass方法,可以直接在类名加上.class来获取,这种方式可以用于基本数据类型。

    使用Class.forName()方法

    这个方法要使用一个类的完整路径,就可以使用Class.forName("类的完整路径")来得到相应的Class。

     try {
            Class mclass1 = Class.forName("main.fanshe.Person");
            System.out.println(mclass1.getName());
         } catch (ClassNotFoundException e) {
                e.printStackTrace();
         }
    

    注意:使用Class的newInstance()方法来创建对应类的实例,需要有默认的构造器,执行newInstance()方法实际上市利用默认构造器来创建该类的实例。

    Class mclass1 = Class.forName("main.fanshe.Person");
    Object o = mclass1.newInstance();
    

    通过反射获取成员变量

    常用获取成员属性的方法

    
    Field[] declaredFields = mclass1.getDeclaredFields();//获取Class对象的所有属性
    
    Field[] fields = mclass1.getFields();//获取class对象的public属性
    
    Field ageField = mclass1.getDeclaredField("age");//获取class指定属性
    
    Field desFiedl = mclass1.getField("name");//获取class指定的public属性
    
    
    

    如果获取到属性可以用过set方法进行修改例如:

     Field ageField = mclass1.getDeclaredField("age");//获取class指定属性
     ageField.setInt(o,22);
    

    如果这个属性是用private修饰的话,这样写的话代码会报错

    java.lang.IllegalAccessException: Class main.fanshe.Main can not access a member of class main.fanshe.Person with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
        at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
        at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
        at java.lang.reflect.Field.setInt(Field.java:946)
        at main.fanshe.Main.main(Main.java:50)
    
    

    这时我们要添加 ageField.setAccessible(true);这个方法来声明这个变量是可以访问的就没问题了,但是使用这个方法也可能会导致些其他问题,例如
    在运行时虽然你通过反射修改了变量 a 的值,但其他部分可能还在使用原来的值。

    通过反射获取成员方法

    Method[] methods = mclass1.getDeclaredMethods();//获取class对象的所有声明方法
    Method[] allMethods = mclass1.getMethods();//获取class对象的所有public声明方法
    Method method = mclass1.getMethod("getAge");//根据方法名返回方法
    Method method2 = mclass1.getMethod("getAge",String.class);//根据带指定形参列表的public方法
    System.out.println(method.toString());
    

    可以通过method.invoke(o);这个方法调用反射到的方法。

    总结

    反射还有好多其他方法,可以通过查询API获知,例如获取构造方法等,功能貌似还是比较强大的,但是反射的一些操作可能会引起性能消耗,例如修改某个成员变量的时候,需要引发验证访问权限等额外操作等。所以使用反射的时候也许要考虑下性能方面的问题。

    本篇文章参考:http://blog.csdn.net/u011240877/article/details/54604212

    相关文章

      网友评论

        本文标题:java基础反射知识总结

        本文链接:https://www.haomeiwen.com/subject/xqezixtx.html