美文网首页
Java反射机制及API使用

Java反射机制及API使用

作者: gyl_coder | 来源:发表于2018-05-17 18:10 被阅读15次

    原文地址

    反射简单来说,就是动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道并获取这个类的所有属性和方法。

    Java反射机制的作用:

    • 在运行时判断任意一个对象所属的类。
    • 在运行时判断任意一个类所具有的成员变量和方法。
    • 在运行时任意调用一个对象的方法
    • 在运行时构造任意一个类的对象

    反射机制的优缺点是什么?

    反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性。

    它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
    满足我们的要求。这类操作总是慢于只直接执行相同的操作。

    获取Class对象的三种方式

    package com.gyl;
    
    public class Student {
        public int no;
        public String sex;
    
        private String name;
        private int age;
        
        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;
        }
    
        /*
         * 构造方法
         */
        
       Student(String str){  
           System.out.println("(默认)的构造方法 s = " + str);  
       }  
         
       //无参构造方法  
       public Student(){  
           System.out.println("调用了公有、无参构造方法执行了。。。");  
       }  
         
       //有一个参数的构造方法  
       protected Student(char name){  
           System.out.println("姓名:" + name);  
       }  
         
       //有多个参数的构造方法  
       public Student(String name ,int age){  
           System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。  
       }  
         
       //私有构造方法  
       private Student(int age){  
           System.out.println("私有的构造方法   年龄:"+ age);  
       }
        
    }
    
    package com.gyl;
    
    import java.lang.reflect.Constructor;
    
    public class Main {
        public static void main(String[] args) throws ClassNotFoundException {
            Student student = new Student();
            
            /*
             * JAVA反射--获取Class对象的三种方式
             */
            
            // 通过对象名.getClass()方法获取
            Class stuClass = student.getClass();
            System.out.println("stuClass is "+stuClass.getName());      
            
            // 通过类名.class方式获得
            Class stuClass1 = Student.class;
            System.out.println("stuClass1 is "+stuClass1.getName());
            System.out.println(stuClass == stuClass1);
            
            // 通过Class.forName()方法获得
            Class stuClass2 = Class.forName("com.gyl.Student");
            System.out.println("stuClass2 is "+stuClass2);
            System.out.println(stuClass1 == stuClass2);
        }
    }
    
    Output:
    stuClass is com.gyl.Student
    stuClass1 is com.gyl.Student
    true
    stuClass2 is class com.gyl.Student
    true
    

    在运行期间,一个类,只有一个Class对象产生。三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都选第三种,一个字符串可以传入也可写在配置文件中等多种方法。

    反射API

    获取构造方法

    // 返回指定参数类型 public的构造器。 
    Constructor<T> getConstructor(类<?>... parameterTypes) 
    
    // 返回指定参数类型的构造器(public, protected, private)。
    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 
    
    // 返回所有的public类型的构造器
    Constructor<?>[] getConstructors() 
    
    // 返回所有的构造器
    Constructor<?>[] getDeclaredConstructors() 
    
    package com.gyl;
    
    import java.lang.reflect.Constructor;
    
    public class Main {
        public static void main(String[] args) throws ClassNotFoundException {
    
            // 通过Class.forName()方法获得Class对象
            Class stuClass = Class.forName("com.gyl.Student");
            
            
            System.out.println("************返回所有public构造方法************");
            Constructor[] constructors = stuClass.getConstructors();
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
            }
            /*
             * Output:
             * ************返回所有public构造方法************
             *  public com.gyl.Student()
             *  public com.gyl.Student(java.lang.String,int)
             */
        
            System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");  
            Constructor[] constructors2 = stuClass.getDeclaredConstructors();
            for (Constructor constructor : constructors2) {
                System.out.println(constructor);
            }
            /*
             * Output:
             * ************所有的构造方法(包括:私有、受保护、默认、公有)***************
             *  private com.gyl.Student(int)
             *  public com.gyl.Student()
             *  protected com.gyl.Student(char)
             *  public com.gyl.Student(java.lang.String,int)
             *  com.gyl.Student(java.lang.String)
             */
            
            
            Constructor constructor;
    
            System.out.println("************返回指定类型的 public构造器************");
            try {
                constructor = stuClass.getConstructor(String.class, int.class);
                System.out.println(constructor);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
            /*
             * Output:
             * ************返回指定类型的 public构造器************
             * public com.gyl.Student(java.lang.String,int)
             * 
             * 如果指定参数的构造器是非public类型的 则抛出java.lang.NoSuchMethodException异常
             */
              
            System.out.println("************返回指定类型的构造器************");
            try { 
                constructor = stuClass.getDeclaredConstructor(int.class);
                System.out.println(constructor);            // char.class
            } catch (NoSuchMethodException e) {             // String.class, int.class
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
            /*
             * Output:
             * ************返回指定类型的构造器************
             * public com.gyl.Student(java.lang.String,int)
             * protected com.gyl.Student(char)
             * private com.gyl.Student(int)
             */
        }
    }
    

    获取变量

    // 根据变量名获得对应的变量,访问权限不限;
    Field getDeclaredField(String name) 
    
    // 获得类中所有属性变量 
    Field[] getDeclaredFields()
    
    // 根据变量名获取对应public类型的属性变量
    Field getField(String name) 
    
    // 获取类中所有public类型的属性变量
    Field[] getFields() 
    
    package com.gyl;
    
    import java.lang.reflect.Field;
    
    public class Main {
        public static void main(String[] args) throws ClassNotFoundException {
    
            // 通过Class.forName()方法获得Class对象
            Class stuClass = Class.forName("com.gyl.Student");
            
            try {
                Field field1 = stuClass.getField("sex");
                System.out.println(field1);
                
                Field field = stuClass.getDeclaredField("name");
                System.out.println(field);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
            /*
             * Output:
             * public java.lang.String com.gyl.Student.sex
             * private java.lang.String com.gyl.Student.name
             * 如果使用getField方法指定了一个非public类型的属性,则抛出java.lang.NoSuchFieldException异常
             */
            
            Field[] fields1 = stuClass.getFields();
            Field[] fields = stuClass.getDeclaredFields();
            System.out.println("************返回所有public属性************");
            for (Field field : fields1) {
                System.out.println(field);
            }
            /*
             * Output:
             * ************返回所有public属性************
             *  public int com.gyl.Student.no
             *  public java.lang.String com.gyl.Student.sex
             */
    
            System.out.println("************返回所有属性************");
            for (Field field : fields) {
                System.out.println(field);
            }
            /*
             * Output:
             * ************返回所有属性************
             *  public int com.gyl.Student.no
             *  public java.lang.String com.gyl.Student.sex
             *  private java.lang.String com.gyl.Student.name
             *  private int com.gyl.Student.age
             */
        }
    }
    

    获取方法

    // 获取“名称是name,参数是parameterTypes”的public的函数(包括从基类继承的、从接口实现的所有public函数)
    public Method  getMethod(String name, Class[] parameterTypes)
    
    // 获取全部的public的函数(包括从基类继承的、从接口实现的所有public函数)
    public Method[]  getMethods()
    
    // 获取“名称是name,参数是parameterTypes”,并且是类自身声明的函数,包含public、protected和private方法。
    public Method  getDeclaredMethod(String name, Class[] parameterTypes)
    
    // 获取全部的类自身声明的函数,包含public、protected和private方法。
    public Method[]  getDeclaredMethods()
    
    // 如果这个类是“其它类中某个方法的内部类”,调用getEnclosingMethod()就是这个类所在的方法;若不存在,返回null。
    public Method  getEnclosingMethod()
    
    
    package com.gyl;
    
    import java.lang.reflect.Method;
    
    public class Main {
        public static void main(String[] args) throws ClassNotFoundException {
    
            // 通过Class.forName()方法获得Class对象
            Class stuClass = Class.forName("com.gyl.Student");
            
            Method method;
            try {
    //          method = stuClass.getMethod("getName");
                method = stuClass.getDeclaredMethod("getAge");
                System.out.println(method);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
            
            
            System.out.println("*********输出所有方法********");
            Method[] methods = stuClass.getDeclaredMethods();
            for (Method method2 : methods) {
                System.out.println(method2);
            }
            /*
             * Output:
             * public int com.gyl.Student.getAge()
             *  *********输出所有方法********
             *  public java.lang.String com.gyl.Student.getName()
             *  public void com.gyl.Student.setName(java.lang.String)
             *  void com.gyl.Student.print(java.lang.String)
             *  public int com.gyl.Student.getAge()
             *  public void com.gyl.Student.setAge(int)
             */
        }
    }
    

    通过反射越过泛型检查

    泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的

    import java.lang.reflect.Method;  
    import java.util.ArrayList;  
     
    /* 
    * 通过反射越过泛型检查 
    *  
    * 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值? 
    */  
    public class Demo {  
       public static void main(String[] args) throws Exception{  
           ArrayList<String> strList = new ArrayList<>();  
           strList.add("aaa");  
           strList.add("bbb");  
             
       //  strList.add(100);  
           //获取ArrayList的Class对象,反向的调用add()方法,添加数据  
           Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象  
           //获取add()方法  
           Method m = listClass.getMethod("add", Object.class);  
           //调用add()方法  
           m.invoke(strList, 100);  
             
           //遍历集合  
           for(Object obj : strList){  
               System.out.println(obj);
               System.out.println(obj.getClass());
           }  
            /*
             *Output:
             * aaa
             * class java.lang.String
             * bbb
             * class java.lang.String
             * 100
             * class java.lang.Integer
             */
       }  
    }
    

    其他方法请参考Java jdk,本文参考自Java jdk1.8

    相关文章

      网友评论

          本文标题:Java反射机制及API使用

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