zoukankan      html  css  js  c++  java
  • Java技术——Java反射机制分析

    1. Java的反射机制

    动态语言是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVAC++一样,都不是动态语言。但Java它却有着一个非常突出的动态相关机制:反射

     

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

     

    Java反射机制主要提供了以下功能

    1)在运行时判断任意一个对象所属的类

    2)在运行时构造任意一个类的对象

    (这一条在下面没有展示实例,但在之前写过的一篇Java中创建对象的5种方式中有所介绍,有兴趣的可以参考查看。)

    3)在运行时判断任意一个类所具有的成员变量和方法

    4)在运行时调用任意一个对象的方法

    5)生成动态代理

     

    2. Java反射API

    反射API用来生成在当前Java虚拟机中的类、接口或者对象的信息。

    Class类:反射的核心类,可以获取类的属性,方法等内容信息。

    Field类:Java.lang.reflect.表示类的属性,可以获取和设置类的中属性值

    Method类:Java.lang.reflect。表示类的方法,它可以用来获取类中方法的信息或者执行方法

    Construcor类:Java.lang.reflect。表示类的构造方法

     

    3.反射常见用法

    3.1 判断对象是否属于反射得到的类(isInstance

    class S {   
    }    
    public class IsInstance {   
       public static void main(String args[]) {   
          try {   
               Class cls = Class.forName("S");  //创建了一个S类的Class对象
               boolean b1 = cls.isInstance(new Integer(37));   
               System.out.println(b1);   //fasle
               boolean b2 = cls.isInstance(new S());   
               System.out.println(b2);   //true
          }   
          catch (Throwable e) {   
               System.err.println(e);   
          }   
       }   
    } 


    3.2 获取某个反射类的所有属性字段

    /** 
     * 获取反射类的所有属性字段 
     *  
     * @param ownerClass 反射的类 
     * @return 
     * @throws Exception 
     */  
    public Field[] getProperty(Class ownerClass) throws Exception {  
      
        //获取该类所有属性字段  
        //Field[] fields = ownerClass.getFields();//只获取public访问权限的属性字段(包括父类的)  
        Field[] fields = ownerClass.getDeclaredFields();//只获取该类的所有访问权限的属性(不含父类)  
          
        //输出所有属性字段  
        for(int i=0;i<fields.length;i++){  
            System.out.println("属性:"+fields[i]);  
        }  
      
        return fields;  
    }  

    3.3 获取反射类的某个public属性值

    /** 
     * 获取反射类的某个public属性值 
     *  
     * @param ownerClass 反射的类 
     * @param fieldName 属性名 
     * @return 
     * @throws Exception 
     */  
    public Object getProperty(Object owner,String fieldName) throws Exception {  
          
        //得到对象所属类  
        Class ownerClass = owner.getClass();  
      
        //获取该类的某个属性  
        Field field = ownerClass.getField(fieldName);  
          
        //获取某个对象的特定属性  
        Object property = field.get(owner);  
          
        //输出该属性信息  
        System.out.println(fieldName+"的属性值:"+property.toString());  
      
        return property;  
      
    }  


    3.4 获取反射类的该中的所有方法

    /** 
     * 获取反射类的该中的所有方法 
     * @param ownerClass 反射的类 
     * @return 
     * @throws Exception 
     */  
    public Method[] getMethods(Class ownerClass) throws Exception {  
      
        //获取该类所有方法  
        //Field[] fields = ownerClass.getMethods();//只获取public访问权限的方法(包括父类的)  
        Method[] methods = ownerClass.getDeclaredMethods();//只获取该类的所有访问权限的方法(不含父类)  
      
        //输出所有方法  
        for(int i=0;i<methods.length;i++){  
            System.out.println("方法:" +methods[i]);  
        }  
      
        return methods;  
    }  


    3.5 执行反射类的该中的某个方法

    /** 
     * 执行反射类的该中的某个方法 
     * @param ownerClass 反射的类 
     * @param methodName 方法名 
     * @return 
     * @throws Exception 
     */  
    public Object invokeMethod(Object owner,String methodName,Object[] args) throws Exception {  
      
        //得到对象所属类  
        Class ownerClass = owner.getClass();  
      
        //获取该类的某个方法  
        Method method = ownerClass.getMethod(methodName, null);  
          
        //执行某个对象的方法  
        Object result = method.invoke(owner, args);  
          
        //输出结果信息  
        System.out.println("结果返回值:"+ result);  
      
        return result;  
    }  


    实例演示方法:

    /** 
     * 测试反射常用方法 
     */  
    public void refTest(){  
        String className = "com.java.reflecttest.Student";  
      
        try {  
              
            //通过反射机制,使用类装载器,装载该类  
            Class<?> stu = Class.forName(className);  
            Object objStu = stu.newInstance();  
                      
              
            //获取反射类的所有属性  
            System.out.println("
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ");  
            System.out.println("调用 getProperty 方法,获取Student类的所有属性");  
            getProperty(stu);  
              
              
            //获取反射类的某个属性值  
            System.out.println("
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ");  
            System.out.println("调用 getProperty 方法,获取Student类的NAME属性值");  
            getProperty(objStu,"NAME");  
              
              
            //获取反射类的所有方法  
            System.out.println("
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ");  
            System.out.println("调用 getMethods 方法,获取Student类的所有方法");  
            getMethods(stu);  
              
            //执行反射类的getInfo方法  
            System.out.println("
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ");  
            System.out.println("调用 invokeMethod 方法,执行Student类的getInfo方法");  
            invokeMethod(objStu, "getInfo", null);  
              
              
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

    演示所用的Student类:

    package com.java.reflecttest;  
      
    /** 
     * 学生信息类 
     *  
     * @author Longxuan 
     * 
     */  
    public class Student {  
      
        /** 
         * 学号 
         */  
        private String stuId ;  
          
        /** 
         * 学号 
         */  
        public String STUID;  
          
        /** 
         * 姓名 
         */  
        private String name ;  
          
        /** 
         * 姓名 
         */  
        public String NAME;  
      
        /** 
         * 年龄 
         */  
        private int age;  
          
        /** 
         * 年龄 
         */  
        public int AGE;  
          
        /** 
         * 班级 
         */  
        private String classid;  
          
      
      
          
        public String getStuId() {  
            return stuId;  
        }  
      
        public void setStuId(String stuId) {  
            this.stuId = stuId;  
        }  
      
        public String getName() {  
            return name;  
        }  
      
        public void setName(String name) {  
            this.name = name;  
        }  
      
        public int getAge() {  
            return age;  
        }  
      
        public void setAge(int age) {  
            this.age = age;  
        }  
      
        public String getClassid() {  
            return classid;  
        }  
      
        public void setClassid(String classid) {  
            this.classid = classid;  
        }  
          
          
        /** 
         * 输出学生信息 
         */  
        public void getInfo(){  
            System.out.println("学生信息:
    学号:"+stuId+"	姓名:"+name+"	年龄:"+age+"	班级:"+classid);  
        }  
          
        /** 
         * 构造函数 
         */  
        public Student(){  
            init();  
        }  
          
          
        /** 
         * 私有初始化方法 
         */  
        private void init(){  
            this.name = "张三";  
            this.stuId ="1001";  
            this.age = 14;  
            this.classid = "A001";  
            this.NAME = name;  
            this.AGE = age;  
            this.STUID = stuId;  
        }  
          
    }  


    运行结果:


    4. 反射的效率

    Stackoverflow上认为反射比较慢的程序员主要有如下看法,如果你面试遇到了,可以这样回答:

    1)验证等防御代码过于繁琐,这一步本来在link阶段,现在却在计算时进行验证。

    2)产生很多临时对象,造成GC与计算时间消耗。

    3)由于缺少上下文,丢失了很多运行时的优化,比如JIT(它可以看作JVM的重要评测标准之一)

     

    当然,我个人的看法是,现代JVM也不是非常慢了,它能够对反射代码进行缓存以及通过方法计数器同样实现JIT优化,所以反射不一定慢。更重要的是,很多情况下,你自己的代码才是限制程序的瓶颈。因此,在开发效率远大于运行效率的的基础上,大胆使用反射,放心开发吧。


    文章转自:http://blog.csdn.net/xiaoxian8023/article/details/9206055

    http://www.jianshu.com/p/f83556bcae59



  • 相关阅读:
    201671010119 2016-2017-2《Java程序设计》第十四周学习心得
    201671010119 2016-2017-2《Java程序设计》第十三周学习心得
    201671010119 2016-2017-2《Java程序设计》第十二周学习心得
    201671010119 2016-2017-2《Java程序设计》第十一周学习心得
    201671010119 2016-2017-2《Java程序设计》第十周学习心得
    201671010119 2016-2017-2《Java程序设计》第九周学习心得
    201671010118 2016-2017-2《Java程序设计》 面向对象程序设计课程学习进度条
    201671010118 2016-2017-2《Java程序设计》 第十八周学习心得
    201671010118 2016-2017-2《Java程序设计》 第十七周学习心得
    201671010118 2016-2017-2《Java程序设计》 第十六周学习心得
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461566.html
Copyright © 2011-2022 走看看