zoukankan      html  css  js  c++  java
  • Java的反射机制

    反射给人的第一感觉:

    常规调用是obj.field. / obj.method()
    反射则是field.get(obj). / method.invoke(obj)
    执行的主体发生了变化,非常适合于对象未定义的场景下,例如框架等通用场景。

    反射的定义:

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为JAVA语言的反射机制。

    反射的API:

    // Class类 Constructor类
    @Test
    public void demo1() throws Exception {
        // Class.forName(String class). 用于加载类的.class文件并封装为Class对象
        Class class1 = Class.forName("com.imooc.reflect.test.Person");
        // 获得无参构造
        Constructor c = class1.getConstructor();
        // 实例化对象 返回Object
        Person person = (Person)c.newInstance();
        person.eat();
    }
    
    @Test
    public void demo2() throws Exception{
        Class class2 = Class.forName("com.imooc.reflect.test.Person”);
        // 获得带参构造
        Constructor c = class2.getConstructor(String.class, String.class);
        Person person = (Person)c.newInstance("张三","男");
        person.eat();
    }
    
    // Field类
    @Test
    public void demo1() throws Exception{
        Class class1 = Class.forName("com.imooc.reflect.test.Person");
        // 只能获得公有属性
        Field field = class1.getField("name");
        Person p = (Person)class1.newInstance();
        // 设置对象属性值
        field.set(p, "李四”);
        // 获得对象属性值 返回Object
        Object obj = field.get(p);
        System.out.println(obj);
    
    }
    
    @Test
    public void demo2() throws Exception{
        Class class1 = Class.forName("com.imooc.reflect.test.Person”);
        // 获得所有属性,不论公有还是私有
        Field field = class1.getDeclaredField("sex");
        Person p = (Person)class1.newInstance();
        // 私有属性要设置可访问的权限
        field.setAccessible(true);
        field.set(p,"男");
        Object obj = field.get(p);
        System.out.println(obj);
    }
    
    // Method类
    @Test
    public void demo1() throws Exception{
        Class class1 = Class.forName("com.imooc.reflect.test.Person");
        Person p = (Person)class1.newInstance();
        // 获得公有方法
        Method method = class1.getMethod("eat");
        method.invoke(p);
    
    }
    
    @Test
    public void demo2() throws Exception{
        Class class1 = Class.forName("com.imooc.reflect.test.Person");
        Person p = (Person)class1.newInstance();
        // 获得私有方法
        Method method = class1.getDeclaredMethod("run”);
        // 私有方法执行前要设置权限
        method.setAccessible(true);
        method.invoke(p);
    
    }
    
    @Test
    public void demo3() throws Exception{
        Class class1 = Class.forName("com.imooc.reflect.test.Person");
        Person p = (Person)class1.newInstance();
        // 获得私有带参方法
        Method method = class1.getDeclaredMethod("hello", String.class);
        method.setAccessible(true);
        System.out.println(method.invoke(p, "张三"));
    }
    

    思考:为什么要有反射机制?

    JAVA是一个完全面向对象的语言,但对象往往是个性的,围绕着对象展开的代码也是个性的(对象代码),逻辑上有个性就会有共性,那如果要实现一些共性的场景比如框架,该怎么办?
    共性的代码需要围绕着共性的实体展开,比如Class对象、Constructor对象、Field对象、Method对象,所有的类都具备这四种实体,所以这些是共性的。在共性的场景中,Class、Constructor等是行为主体,而个性的对象实例则成为行为客体,这是反射中的一个反转点。
    除了行为主体不同,共性场景的实现还要求有足够的权限。由于个性实例是复杂多样的,共性代码想要包罗万象必然需要被授权访问这些实例的所有内容,这是反射的另一个要点。
    有时我们觉得有了反射机制那封装和访问修饰符还有什么用吗?在我看来由于对象代码和反射机制针对的场景不同,所以不存在冲突。如果硬要在对象代码中使用反射,那可能是代码编写者出现了问题。

  • 相关阅读:
    datagridview 批量更新、日期设置、指定列弹出右键菜单
    CAD ObjectARX扩展工具的源码(二)
    ObjextARX-VS2005-字符串转换
    二叉搜索树(二叉查找树)
    贪婪算法-货物装载问题
    Messagebox.Show()常用参数的讨论
    关于矩形排样问题(三)
    单纯形法实现一维管材排料最优化
    [转载]共享一些常用的代码
    转载]取硬盘ID的API实现
  • 原文地址:https://www.cnblogs.com/Peter2014/p/10997067.html
Copyright © 2011-2022 走看看