美文网首页
通过一例子窥探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反射

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

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射

    Java反射Java反射API获取Class对象通过反射创建实例对象,调用公共方法通过反射调用私有方法 一.Jav...

  • [JAVA学习笔记] 反射机制

    [JAVA学习笔记] 反射机制 Java的反射通过Class类和java.lang.reflect类库实现。通过它...

  • Java反射之具体使用

    一、反射 反射机制在Java中十分重要,那到底什么是反射机制?举个例子,正常情况下如果已经有一个类,那肯定可以通过...

  • java反射-第3篇

    例子 通过反射动态给对象赋值

  • 9012年了,别说java反射慢了

    java 反射 java反射 调用 通过Method.invoke 委托给sun.reflect.MethodAc...

  • java 反射基础

    1.java反射基础 2.java反射进阶 反射的两个显著的作用 反编译: .class —> .java 通过...

  • JVM的反射调用实现

    如何执行反射调用 Java的反射调用是通过java.lang.reflect.Method的invoke调用执行,...

  • Java注解

    Java注解(Annotation)是通过在java源文件上添加标记字段,然后通过反射的反射在编译或者运行时获取这...

网友评论

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

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