zoukankan      html  css  js  c++  java
  • 12 反射

    12.1  反射的概念

    12.1.1 反射机制

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

      理解反射首先要明确一个概念:那就是动态语言!因为我在学习时对“动态获取类中信息”很困惑。

      动态语言:程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。

      从这个观点出发Java语言不是动态语言,所以Java有了一个非常突出的动态相关机制--Reflection,可以在运行时加载,探知,使用编译时期完全未知的classes,也就是说Java可以加载一个运行时才知道名称的class。也就是说Java反射机制是在运行状态中,对于任意一个类(class文件<字节码文件>),都能知道这个类的属性和方法。对于任意一个对象,都能调用它的属性和方法。这种动态获取类的信息以及动态调用对象的方法的功能成为Java语言的反射机制。简单的说:反射就是把Java类中的各种成分映射成相应的java类。

    12.1.2 反射的好处:

    反射极大的增强了程序的扩展性。

    12.1.3 反射是使用步骤

    步骤:

    1,获得Class对象,就是获得指定名称的字节码文件对象。

    2,实例化对象,获类的属性,方法和构造函数。

    3,调用构造函数创建对象,访问属性,调用方法。

    12.2 Class类

    1字节码

         当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,一个类编译成class文件放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来。

    2 Class类的由来

      所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class(描述字节码文件的对象)。Class类中包含属性有field(字段)、method(方法)、construction(构造函数)。要想对一个类进行内容的获取,必须要先获取该字节码文件的对象。该对象是Class类型。Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。每一个字节码就是class的实例对象。如:classcls=Data.class;

    3 Class和class的区别

            1)class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。

            2)Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。例如人对应的是Person类,Java类对应的就是Class。Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。

    4 获取Class对象的三种方式

            加载XX.class文件进内存时就被封装成了对象,该对象就是字节码文件对象

    1).通过对象的getClass方法进行获取。

            如:Class clazz=new Person().getClass();//Person是一个类名

            弊端:每次都需要具体的类和该类的对象,以及调用getClass方法。

    2).任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应 Class对象。

            如:Class clazz=Person.class;//Person是一个类名

            弊端:还是要使用具体的类,和该类中的一个静态属性class完成。

    3). 这种方式较为简单,只要知道类的名称即可。不需要使用该类,也不需要去调用具 体的属性和行为。就可以获取到Class对象了。

            如:String className=”Person”;

    Class clazz=Class.forName(className);//Person是一个类名

            这种方式仅知道类名就可以获取到该类字节码对象的方式,利于扩展。

    package reflect;
    
    public class Person {
        private String name;
        private int age;
        private String address;
        public Person() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Person(String name, int age, String address) {
            super();
            this.name = name;
            this.age = age;
            this.address = address;
        }
        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 getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
    }
    package reflect;
    /*
     * 反射: 通过class文件的对象,获取构造函数、字段、方法的操作
     * 
     * 学习反射的目的:
     *         有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private私有,所以JDK的帮助文档没有提供该方法
     *         如果,必须要用这个方法, 我们可以通过反射的方式来获取,进行使用
     * 
     * 构造函数: Constructor
     * 字段:Field
     * 方法:Method
     * 
     * 
     * 如何获取Person类的 字节码文件对象呢?
     * 方式1:  getClass(): 返回进行时的类
     * 方式2: 数据类型.class 静态属性,来获取当前数据类型的字节码文件对象
     * 方式3: public static Class forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象
     * 
     */
    public class ReflectDemo {
    
        public static void main(String[] args) {
            //反射机制获取当前正在运行的类
    //        getClassTest1();
            //反射机制获取当前正在运行类的字节码文件
            getClassTest2();
            getClassTest3();
    
        }
        //通过反射机制,获取当前正在运行的类的字节码文件的对象
        //方式一:对象.getClass()
        public static void getClassTest1(){    
            Person p1 = new Person();
            Person p2 = new Person();
            Class c1 = p1.getClass();
            Class c2 = p2.getClass();
            if (p1==p2) {
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"p1和p2是一个对象,地址和内容都一致;");
            } else {
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"p1和p2不是一个对象,地址或内容不一致;");
            }
            if (c1==c2) {
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;");
            } else {
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;");
            }
        }
        //通过反射机制,获取当前正在运行的类的字节码文件的对象
        //方式一:类名.class   静态属性,来获取当前数据类型的字节码文件对象
        public static void getClassTest2(){
            Class c1 = Person.class;
            Class c2 = Person.class;
            if(c1==c2){
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;");
            }else {
                System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;");
            }
        }
        // 方式3: public static Class forName(String className)
        // 返回与带有给定字符串名的类或接口相关联的 Class 对象
        // className : 类的全路径名称 包名.类名
        public static void getClassTest3(){
            try {
                //注意如果不写全路径名,会出现ClassNotFound异常
                Class c1 = Class.forName("reflect.Person");
                Class c2 = Class.forName("reflect.Person");
                if(c1==c2){
                    System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;");
                    System.out.println(c1);
                }else {
                    System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;");
                }
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    
    }

    12.3 常用方法

    12.3.1 获取构造函数

    package reflect;
    
    public class Student {
        public String name;
        public int age;
        private String address;
        public Student() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public Student(String name, String address) {
            super();
            this.name = name;
            this.address = address;
        }
        //私有的构造函数
        private Student(String name, int age, String address) {
            super();
            this.name = name;
            this.age = age;
            this.address = address;
        }
        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 getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
    }
    package reflect;
    
    import java.lang.reflect.Constructor;
    
    /*
     * 反射:
     *         
     * Class类中的方法:
     *         构造函数: Constructor
     * public Constructor getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
     *         public Constructor[] getConstructors() : 获取所有的公共的构造函数
     *         public Constructor[] getDeclaredConstructors(): 获取所有的构造函数
     */
    public class ReflectConstructorDemo {
    
        public static void main(String[] args) {
            //根据参数类型获取指定公共构造函数
            getConstructorTest();
            //获取所有的公共构造函数
            getConstrnctorsTest();
            //获取指定的构造函数(公有,私有)
            getDeclaredConstructorTest();
            //获取所有的公共构造函数(公有,私有)
            getDeclaredConstructorsTest();
    
        }
        //获取指定的公共构造函数
        public static void getConstructorTest(){
            Class c = Student.class;
            try {
                Constructor conPub = c.getConstructor(String.class,int.class);
                System.out.println(conPub);
                
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //获取指定的私有构造函数,注意只能获取公共的构造函数,访问私有会报出java.lang.NoSuchMethodException: reflect.Student.<init>(java.lang.String, int, java.lang.String)
    //        try {
    //            Constructor conPri = c.getConstructor(new Class[] {String.class,int.class,String.class});
    //            System.out.println(conPri);
    //        } catch (NoSuchMethodException | SecurityException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        }
        }
        //获取所有的公共构造函数
        public static void getConstrnctorsTest(){
            Class c = Student.class;
            Constructor[] conPub = c.getConstructors();
            for (Constructor constructor : conPub) {
                System.out.println("获取到的所有的公共的构造函数:"+constructor);
            }
        }
        //获取指定的构造函数(公共和私有都可以获取)
        public static void getDeclaredConstructorTest(){
            Class c = Student.class;
            try {
                Constructor conPub = c.getDeclaredConstructor(new Class[]{String.class,int.class});
                System.out.println("获取公共的构造函数:"+conPub);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class);
                System.out.println("获取私有的构造函数:"+conPri);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //获取所有的构造函数(公共和私有都可以获取)
        public static void getDeclaredConstructorsTest(){
            Class c = Student.class;
            Constructor[] con = c.getDeclaredConstructors();
            for (Constructor constructor : con) {
                System.out.println("获取所有的公共构造函数:"+constructor);
            }
        }
    
    }

    12.3.2 获取当前字节码实例

    package reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    
    /*
     * public Constructor getConstructor(Class<?>... parameterTypes)
     * 
     * 通过构造函数, 创建对象
     * public Object newInstance(Object... initargs)
     * 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
     */
    public class NewInstanceByConstructorDemo {
    
        public static void main(String[] args) {
            //通过构造函数创建实例对象
            getPublicInstanceByConstructorTest();
            //暴力进入,通过私有构造获取实例
            setAccessibleTest();
        }
        //通过构造函数创建实例对象,注意不能创建私有的构造函数,否则报出错误
        //java.lang.IllegalAccessException: Class reflect.NewInstanceByConstructorDemo can not access a member of class reflect.Student with modifiers "private"
        public static void getPublicInstanceByConstructorTest(){
            Class c = Student.class;
    //        try {
    //            //创建私有对象
    //            Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class);
    //            Object obj1 = conPri.newInstance("静",27,"河南");
    //            Object obj2 = conPri.newInstance("静",27,"河南");
    //            if (obj1 == obj2) {
    //                System.out.println("获取到的两个对象是同一个地址!");
    //            }else {
    //                System.out.println("获取到的不是两个对象!");
    //            }
    //        } catch (NoSuchMethodException | SecurityException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        } catch (InstantiationException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        } catch (IllegalAccessException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        } catch (InvocationTargetException e) {
    //            // TODO Auto-generated catch block
    //            e.printStackTrace();
    //        }
            //创建公共构造函数
            
            try {
                Constructor conPub = c.getConstructor(String.class,int.class);
                Object obj1 = conPub.newInstance("静",27);
                Object obj2 = conPub.newInstance("静",27);
                if (obj1==obj2) {
                    System.out.println("创建是同一个对象");
                } else {
                    System.out.println("不是同一个对象");
                }
            } catch (InstantiationException | IllegalAccessException
                    | IllegalArgumentException | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //在上边我们看到私有构造函数创建实例时,报错了,这是java的机制决定的,那么有没有办法让他创建成功呢
        /*
         * 获取Student类中的非public的构造函数,并创建对象
         * 
         * public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
         * 获取指定的构造函数 (包含私有的)
         * 
         * public void setAccessible(boolean flag)
         * 将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
         * 
         * 步骤:
         *         创建一个Class字节码文件对象
         *         获取指定的构造函数  如果是非public的构造函数,需要 强制访问(暴力访问)
         *         创建对象
         */
        public static void setAccessibleTest(){
            Class c = Student.class;
            try {
                Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class);
                //强制访问,暴力进入,(通过私有构造函数获取对象)
                conPri.setAccessible(true);
                Object obj = conPri.newInstance("静",27,"河南");
                System.out.println(obj);
                Object object = conPri.newInstance("静",27,"河南");
                System.out.println(object);
            } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    12.3.3 获取当前字节码中字段

    package reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    
    /*
     * 字段:Field
     * 
     * private String name;
     * int age;
     * public String address;
     *
     * 步骤:
     *     a: 创建class字节码文件对象
     *     b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问
     *     c: 对字段进行操作
     * 
     *  Class中的方法:
     *      public Field[] getFields() : 获取 public 修饰的 所有字段
     *         public Field[] getDeclaredFields(): 获取所有的字段(包含私有)
     *         public Field getDeclaredField(String name):获取指定的字段,包含私有
     *         public Field getField(String name): 获取指定的字段
     * 
     * Field中的方法:
     *         public void set(Object obj, Object value):  为指定对象中的当前字段, 赋值
            
            Person p1;
            Person p2;
            addressField.set( p1,"上海");
     * 
     */
    public class ReflectFieldDemo {
    
        public static void main(String[] args) {
            //获取指定的字段(公共的),操作字段
            getPubFieldTest();
            //获取指定的字段(私有的),操作字段
            getPriFieldTest();
            //获取所有公共字段
            getPubFieldsTest();
            //获取所有字段(含私有)
            getAllFieldsTest();
    
        }
        //获取指定的字段(公共的)
        public static void getPubFieldTest(){
            //获取字节码对象
            Class c = Student.class;
            //获取指定字段
            try {
                //获取构造函数
                Constructor conPub = c.getConstructor(String.class,int.class);
                //获取实例对象
                Object obj = conPub.newInstance("静",27);
                //获取指定字段
                Field fN = c.getField("name");
                //设置对象字段
                fN.set(obj, "静");
                Field fA = c.getField("age");
                fA.set(obj, 27);
                System.out.println(obj);
                Student stu = (Student) obj;
                System.out.println(stu.getName()+"--"+stu.getAge());
                System.out.println("-------------------------------------");
            } catch (NoSuchFieldException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //获取指定的字段(私有的)
        public static void getPriFieldTest(){
            Class c = Student.class;
            try {
                //获取私有的构造函数
                Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class);
                //暴力获取实例
                conPri.setAccessible(true);
                Object obj = conPri.newInstance("静",25,"河北");
                //获取字段
                Field fN = c.getDeclaredField("name");
                Field fA = c.getDeclaredField("age");
                fA.set(obj, 27);
                Field fAdder = c.getDeclaredField("address");
                //java.lang.IllegalAccessException: Class reflect.ReflectFieldDemo can not access a member of class reflect.Student with modifiers "private"
                //不能直接操作私有字段,否则报错上面,
    //            fAdder.set(obj, "河南");
                fAdder.setAccessible(true);
                fAdder.set(obj, "河南");
                Student stu = (Student) obj;
                System.out.println(stu.getName()+"--"+stu.getAge()+"--"+stu.getAddress());
                System.out.println("-------------------------------------");
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //获取所有的字段(公共)
        public static void getPubFieldsTest(){
            //获取字节码文件
            Class c = Student.class;
            try {
                //获取构造函数
                Constructor conPub = c.getConstructor(String.class,int.class);
                Object obj = conPub.newInstance("静",25);
                //获取所有公共字段
                Field[] f = c.getFields();
                for (Field field : f) {
                    System.out.println(field.get(obj));
                    System.out.println(field);
                    System.out.println("-------------------------------------");
                }
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
                    
        }
        //获取所有字段(含私有)
        public static void getAllFieldsTest(){
            Class c = Student.class;
            try {
                Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class);
                conPri.setAccessible(true);
                Object obj = conPri.newInstance("静",27,"河南");
                Field[] f = c.getDeclaredFields();
                for (Field field : f) {
                    //字段数组中存在私有,要暴力访问
                    field.setAccessible(true);
                    System.out.println(field.get(obj));
                    System.out.println(field);
                    System.out.println("-------------------------------------");
                }
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    12.3.4 获取当前字节码中的方法

    package reflect;
    
    public class Student {
        public String name;
        public int age;
        private String address;
        public Student() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public Student(String name, String address) {
            super();
            this.name = name;
            this.address = address;
        }
        //私有的构造函数
        private Student(String name, int age, String address) {
            super();
            this.name = name;
            this.age = age;
            this.address = address;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        private void setAge(int age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
    }
    package reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /*
     * 反射方法: Method
     * 
     * 步骤:
     *     a: 创建class 字节码文件对象
     *     b: 获取指定的方法
     *     c: 使用方法(需要前有对象,才能使用方法)
     * 
     * Class类中的方法:
     *         public Method[] getMethods() 获取所有的公共方法(包含父类的)
     *         public Method[] getDeclaredMethods() 获取所有的方法(不包含父类)
     * 
     *         public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
     *                                 name: 想要获取的方法的名字
     *                                 parameterTypes: 获取的方法的参数列表的数据类型
     * 
     *         public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的)
     * 
     * Method类的方法:
     *         public Object invoke(Object obj, Object... args)
     *         调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
     *     暴力访问
     *         public void setAccessible(boolean flag)
     * 
     */
    public class ReflectMethodDemo {
    
        public static void main(String[] args) {
            //获取指定方法(公共)
            getPubMethodTest();
            //获取所有的公共方法
            getPubMethodsTest();
            //获取所有方法,含私有
            getAllMethodsTest();
        }
        //获取指定方法(公共),私有
        public static void getPubMethodTest(){
            //获取字节码文件
            Class c = Student.class;
            //获取构造函数,创建该字节码文件对象实例
            try {
                Constructor conPub = c.getConstructor(String.class,int.class);
                Object obj = conPub.newInstance("静",27);
                //获取指定方法,公共
                Method m1 = c.getMethod("setName", String.class);
                //java.lang.NoSuchMethodException: reflect.Student.setAge(int)
    //            Method m2 = c.getMethod("setAge", int.class);
                //获取指定方法,私有
                Method m2 = c.getDeclaredMethod("setAge", int.class);
                m1.invoke(obj, "岁月静好");
    //java.lang.IllegalAccessException: Class reflect.ReflectMethodDemo can not access a member of class reflect.Student with modifiers "private"
                //暴力调用私有方法
                m2.setAccessible(true);
                m2.invoke(obj, 28);
                Student stu = (Student) obj;
                System.out.println(stu.getName()+"--"+stu.getAge());
                System.out.println("---------------------------------------");
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //获取所有的公共方法
        public static void getPubMethodsTest(){
            Class c = Student.class;
            try {
                Constructor con = c.getConstructor(String.class,int.class);
                Object obj = con.newInstance("静",27);
                Method[] mm = c.getMethods();
                for (Method method : mm) {
                    System.out.println("方法名字:"+method.getName());
                }
                System.out.println("---------------------------------------------");
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //获取所有的方法(含私有)
        public static void getAllMethodsTest(){
            Class c = Student.class;
            try {
                Constructor con = c.getConstructor();
                Object obj = c.newInstance();
                Method[] mm = c.getDeclaredMethods();
                for (Method method : mm) {
                    System.out.println(method.getName());
                }
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    12.3.5 通过反射向集合中添加字符串

    package reflect;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    /*
     *  需求: ArrayList<Integer> list = new ArrayList<Integer>();
     *      向集合中 添加3个字符串
     *  
     *      通过反射来解决该问题
     *      
     *      思路: 
     *          a: 获取  ArrayList 的字节码文件对象
     *          b: 获取 add 方法
     *          c: 使用方法
     *      
     *      注意: 当我们的java文件 生成对应的Class文件的时候, 泛型是不会编译到 class文件中的
     */
    public class ReflectTest {
    
        public static void main(String[] args) {
            //通过反射向集合中添加字符串]
            test();
    
        }
        public static void test(){
            ArrayList<String> al = new ArrayList<>();
            Class c = al.getClass();
            try {
                Method m = c.getMethod("add", Object.class);
                m.invoke(al, "2014");
                m.invoke(al, "2015");
                m.invoke(al, "2016");
                System.out.println("ArrayList:"+al);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

     12.4 反射的优点和缺点

      为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,  

      静态编译:在编译时确定类型,绑定对象,即通过。  

      动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。  

      一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发。

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

  • 相关阅读:
    bzoj4325: NOIP2015 斗地主(爆搜+模拟)
    bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)
    bzoj3555: [Ctsc2014]企鹅QQ (Hash)
    bzoj1455: 罗马游戏 + bzoj2809: Dispatching(可并堆)
    bzoj1510: [POI2006]Kra-The Disks(单调栈)
    bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
    bzoj3048+3049+3050
    bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)
    bzoj1745: [Usaco2005 oct]Flying Right 飞行航班(贪心+map)
    bzoj1724: [Usaco2006 Nov]Fence Repair 切割木板(贪心+堆)
  • 原文地址:https://www.cnblogs.com/lin-jing/p/6914911.html
Copyright © 2011-2022 走看看