美文网首页
通过一例子窥探JAVA反射

通过一例子窥探JAVA反射

作者: 雅俗共赏M | 来源:发表于2017-04-03 16:17 被阅读17次

    在写java中,我们可以通过new关键字来创建一个对象。但是呢,凡事没有绝对。同样地,我们也可以通过别的方法来构造一个对象。这个方法就是:反射。

    这篇文章通过8个Demo()方法来演示反射常用的几种方法:

    • class.forName():传入类路径、动态反射生成一个相应类的Class对象
    • class.newInstance():顾名思义,通过反射得到一个对象。
    • class.getConstructors():获得该类的构造器数组
    • class.getDeclaredFields():获得类属性数组
    • class.getMethods():获得类方法数组
    • class.getClassLoader():获得该类的类加载器
    • method.invoke(class.newInstance())调用该对象的一个方法

    Person类的定义

    class Person {
        private int age;
        private String name;
        public Person() {
     
        }
     
        public Person(int age,String name) {
            this.age = age;
            this.name = name;
        }
     
        public void setAge(int age) {
            this.age = age;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public int getAge() {
            return age;
        }
     
        public String getName() {
            return name;
        }
    }
    

    接口ActionInterface的声明

    interface ActionInterface {
            public void walk(int m);
    }
    

    SuperMan类,继承自Person,实现ActionInterface接口的walk(int m)方法。

    class SuperMan extends Person implements ActionInterface{
        private boolean BlueBriefs;
     
        public void fly() {
            System.out.println("超人会飞耶~");
        }
     
        public void setBlueBriefs(boolean blueBriefs) {
            this.BlueBriefs = blueBriefs;
        }
     
        public boolean isBlueBriefs() {
            return BlueBriefs;
        }
     
        @Override
        public void walk(int m) {
            System.out.println("超人会走耶~~走了" + m + "米就走不动了!");
        }
    }
    

    测试类:八个Demo()方法

    package reflectLearning;
    import java.lang.reflect.*;
     
    /**
     * Created by Nanguoyu on 2016/4/21.
     */
    public class ReflectLearning {
     
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException {
     
            demo1();
            System.out.println("==============================================");
          
            demo2();
            System.out.println("==============================================");
     
            demo3();
            System.out.println("==============================================");
    
            demo4();
            System.out.println("==============================================");
     
            demo5();
            System.out.println("==============================================");
     
            demo6();
            System.out.println("==============================================");
     
            demo7();
            System.out.println("==============================================");
     
            demo8();
            System.out.println("==============================================");
        }
     
        //Demo1.通过java反射机制得到类的包名和类名
        public static void demo1() {
            Person person = new Person();
            System.out.println("Demo1:包名:" + person.getClass().getPackage().getName() + "," + "完整类名:" + person.getClass().getName());
        }
     
        //Demo2.通过Class类的静态方法forName()来动态反射生成一个相应类型的Class
        public static void demo2() throws ClassNotFoundException {
     
            //定义两个类型都未知的Class,设置初值为null,看看如何给它们赋值成Person类
            Class<?> class1 = null;
            Class<?> class2 = null;
     
            //写法1,可能抛出ClassNotFoundException
            class1 = Class.forName("reflectLearning.Person");
            System.out.println("Demo2:(写法1)包名:" + class1.getPackage().getName() + ","
                                + "完整类名:" + class1.getName());
     
            //写法2
            class2 = Person.class;
            System.out.println("Demo2:(写法2)包名:" + class2.getPackage().getName() + ","
                    + "完整类名:" + class2.getName());
        }
    
        /**
         * demo3:通过java反射机制,用class创建类对象【这也就是反射存在的意义所在】
         * @throws ClassNotFoundException
         * @throws IllegalAccessException
         * @throws InstantiationException
         */
    
        public static void demo3() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
            Class<?> class1 = null;
            class1 = Class.forName("reflectLearning.Person");
     
            //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
            Person person = (Person) class1.newInstance();
    
            person.setAge(20);
            person.setName("SmileDay");
            System.out.println("Demo3:" + person.getName() + ":" + person.getAge());
        }
     
     
        /**
         * demo4:通过java反射机制得到一个类的构造函数,并实现创建带参实例对象
         * @throws ClassNotFoundException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         * @throws InstantiationException
         */
        public static void demo4() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class<?> class1 = null;
            Person person1 = null;
            Person person2 = null;
     
     
            class1 = Class.forName("reflectLearning.Person");
    
            //得到一系列构造函数集合
            Constructor<?>[] constructors = class1.getConstructors();
    
            //通过 无参 构造函数来反射生成一个对象
            person1 = (Person) constructors[0].newInstance();
     
            person1.setName("I'm the none param Body");
            person1.setAge(18);
     
            //通过 有参 构造函数来反射生成一个对象
            person2 = (Person) constructors[1].newInstance(20,"I'm the second param Body");
     
            System.out.println("Demo4:" + person1.getName() + ":" + person1.getAge());
            System.out.println("Demo4:" + person2.getName() + ":" + person2.getAge());
     
        }
     
     
        /**
         * Demo5: 通过Java反射机制操作成员变量, set 和 get
         * @throws ClassNotFoundException
         * @throws IllegalAccessException
         * @throws InstantiationException
         * @throws NoSuchFieldException
         */
     
        public static void demo5() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
            Class<?> class1 = null;
            class1 = Class.forName("reflectLearning.Person");
            Object obj = class1.newInstance();
     
            Field personNameField = class1.getDeclaredField("name");
     
            //因为name域属性为private,故要设置为true,方可对其进行操作。
            personNameField.setAccessible(true);
    
            personNameField.set(obj,"大魔王");
    
            System.out.println("Demo5:修改属性之后得到的属性变量的值:" + personNameField.get(obj));
     
            //通过Class的getDeclaredFields()方法来获得一个属性数组
            Field[] fields = class1.getDeclaredFields();
     
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                fields[i].set(obj,"啦啦啦");
                System.out.println("利用之后得到的结果为:" + fields[i].get(obj));
            }
        }
     
        /**
         * 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等
         * @throws ClassNotFoundException
         */
     
        public static void demo6() throws ClassNotFoundException {
            Class<?> class1 = null;
            class1 = Class.forName("reflectLearning.SuperMan");
     
            //取得父类名称
            Class<?> superClass = class1.getSuperclass();
            System.out.println("Demo6:SuperMan类的父类名:" + superClass.getName());
     
            System.out.println("=========================================");
     
            //通过Class的getDeclaredFields()方法来获得一个属性数组
            Field[] fields = class1.getDeclaredFields();
     
            for (int i = 0; i < fields.length; i++) {
                System.out.println("类中的成员:" + fields[i]);
            }
     
            System.out.println("=========================================");
     
            //通过Class的getMethods()方法来获得一个方法数组
            Method[] methods = class1.getMethods();
            for (int i = 0; i < methods.length; i++) {
                System.out.println("Demo6:取得SuperMan类的方法:");
                System.out.println("函数名:" + methods[i].getName());
                System.out.println("函数返回类型:" + methods[i].getReturnType());
                System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
            }
    
            System.out.println("=========================================");
     
            //取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
            Class<?> interfaces[] = class1.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                System.out.println("实现的接口名:" + interfaces[i].getName());
            }
        }
     
     
        /**
         * Demo7: 通过Java反射机制调用类方法
         * @throws ClassNotFoundException
         * @throws NoSuchMethodException
         * @throws IllegalAccessException
         * @throws InstantiationException
         * @throws InvocationTargetException
         */
        public static void demo7() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
            Class<?> class1 = null;
            class1 = Class.forName("reflectLearning.SuperMan");
     
            System.out.println("Demo7:\n调用无参方法fly():");
     
            Method method = class1.getMethod("fly");
            method.invoke(class1.newInstance());
     
            /*
             *通过调用Class的getMethod(String methodName,Class<?> class)
             *来获得一个walk(int m)方法。
             */
            System.out.println("调用有参数方法walk(int m):");
            method = class1.getMethod("walk",int.class);
            method.invoke(class1.newInstance(),100);
        }
     
     
        /**
         * 通过Java反射机制得到类加载器信息
         * @throws ClassNotFoundException
         *
         * Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
         * Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
         * AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
         */
        public static void demo8() throws ClassNotFoundException {
            Class<?> class1 = null;
            class1 = Class.forName("reflectLearning.SuperMan");
            String nameString = class1.getClassLoader().getClass().getName();
            System.out.println("Demo8:类加载器名:" + nameString);
        }
     
    }
    

    总结:Class.forName()方法,是反射的入口,只有当执行了这个方法,得到了一个class对象,那么接着就可以获取所对应的类、对象的各种数据:构造器数组、方法数组、属性数字、父类数组、接口、类加载器等信息。

    参考文章:http://blog.csdn.net/ljphhj/article/details/12858767

    相关文章

      网友评论

          本文标题:通过一例子窥探JAVA反射

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