美文网首页
Java的反射机制

Java的反射机制

作者: 安在成丶 | 来源:发表于2019-07-14 15:30 被阅读0次

    什么是反射

    Java的反射指的是在程序运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。并且对于每一个对象,我们都能够对它的属性和方法进行调用。 我们把这种动态调用对象属性对象方法的功能称为反射机制。


    反射的三种方式

    所谓的反射其实是根据类的字节码文件来获取属性和方法的,也就是.class文件,所以我们就是通过Class对象来获取这些属性和方法。

    而反射一共有三种方式来来获取属性和方法。

    1. 第一种方式:

    Class<?>  getClass() 返回此Object的运行时类

    这个方法是来自Object的方法,Class继承了Object,所以我们可以直接使用这个方法。

    //创建一个对象

    Student student =new Student();

    //获取对象的Class属性

    Class c = student.getClass();

    //获取类名称

    System.out.println(c.getName());

    2.第二种方式

    第二种方式获取和第一种方式类似,可以直接通过类名直接获取class文件

    Class c1 = Student.class;

    //获取类名称

    System.out.println(c1.getName());

    3.第三种方式

    通过类的全路径名获取Class对象,但是这样获取,需要抛出一个ClassNotFoundException异常,如果在指定路径下找不到该类,就会抛出异常。

    public static void main(String[] args)throws ClassNotFoundException {

    Class c2 = Class.forName("demo.demo.Student");

    //获取类名称

        System.out.println(c2.getName());

    }

    一般会选择第三种方式获取类的class文件。


    通过反射获取类的构造方法、方法以及属性

    1.获取构造方法

    可以通过Class的四个方法来获得类的构造方法

    getConstructors()  (获得所有公用的构造方法)

    getConstructor()  (获得公有的 & 无参的构造方法)

    getDeclaredConstructors () (获得所有的构造方法)

    getDeclaredConstructor() (获得私有 & 有参的构造方法)

    需要抛出一个NoSuchMethodException异常,当没找到相应构造方法是抛出。

    具体使用方法如下所示:

    public static void main(String[] args)throws ClassNotFoundException, NoSuchMethodException {

    //加载Class对象

        Class c = Class.forName("demo.demo.Student");

    System.out.println("获得所有公用的构造方法!");

    //获得所有的公用构造方法

        Constructor[] constructors = c.getConstructors();

    for (Constructor constructor: constructors

    ) {

    System.out.println(constructor);

    }

    System.out.println("获得所有的构造方法!");

    //获得所有的构造方法

        Constructor[]  constructors1 = c.getDeclaredConstructors();

    for (Constructor constructor: constructors1

    ){

    System.out.println(constructor);

    }

    System.out.println("获得所有的公有 & 无参的构造方法");

    //获得所有的公有 & 无参的构造方法

    //传入null参数,获取无参的构造方法

        Constructor constructor2 = c.getConstructor(null);

    System.out.println(constructor2);

    System.out.println("获取所有的公有 & 有参的构造方法");

    //获取所有的公有 & 有参的构造方法

    //按照构造方法参数顺序,依次传入构造方法参数的类型,获取公有的有参构造方法

        Constructor constructor3 = c.getConstructor(new Class[]{int.class,String.class,String.class});

    System.out.println(constructor3);

    System.out.println("获取所有的私有 & 有参的构造方法");

    //获取所有的私有 & 有参的构造方法

    //方式与获取公有有参方法的方式类似,只是使用的类方法不一样

        Constructor constructor4 = c.getDeclaredConstructor(new Class[]{String.class});

    System.out.println(constructor4);

    }

    运行结果如下所示:

    2.获取类属性

    获取类属性可以通过两个方法获取:

    getField (获取公用字段)

    getDeclaredField (获取私有字段,公用字段)

    并且有一点需要注意的是,在获取私有字段赋值使用的过程中,需要进行暴力反射。

    也就是需要暂时的关闭Java的权限检查机制,不再检查私有属性的访问权限,可以让我们给私有属性赋值。

    使用 Filed.setAccessible(true) 方法来设置

    https://www.cnblogs.com/fanguangdexiaoyuer/p/6548171.html(关于setAccessible方法更详细内容)

    使用这两个方法需要抛出一个 NoSuchFieldException 异常,在类中找不到相应的字段时抛出。

    具体使用方法如下:

    public static void main(String[] args)throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, InstantiationException {

    //加载Class对象

        Class c = Class.forName("demo.demo.Student");

    System.out.println("获取所有的公有字段!");

    Field[] fields = c.getFields();

    for (Field field : fields) {

    System.out.println(field);

    }

    System.out.println("获取所有的字段(公有,私有)!");

    Field[] fields1 = c.getDeclaredFields();

    for (Field field : fields1) {

    System.out.println(field);

    }

    System.out.println("获取公有字段并赋值使用!");

    //获取指定公有字段

        Field field = c.getField("name");

    //获取一个公有构造方法,并且使用newInstance方法实例化。

        Object obj = c.getConstructor().newInstance();

    //为属性设置值

        field.set(obj,"kk");

    Student student = (Student)obj;

    System.out.println(student.getName());

    System.out.println("获取私有字段并赋值使用!");

    //获取指定私有字段

        Field field1 = c.getDeclaredField("address");

    //获取一个公有构造方法,并且使用newInstance方法实例化。

        Object obj1 = c.getConstructor().newInstance();

    //暴力反射,关闭Java 语言访问控制检查的能力,禁用安全检查,也就是暂时关闭私有权限的访问权限。

        field1.setAccessible(true);

    //为属性设置值

        field1.set(obj1,"kkAddress");

    Student student1 = (Student)obj1;

    System.out.println(student1.getAddress());

    }

    运行结果如下所示:

    3.获取指定方法并使用

    获取类的方法可以通过两个方法来获取

    getMethod(获取公有方法)

    getDeclaredMethod(获取公有方法、私有方法、受保护方法)

    先定义几个不同类型的方法:

    public void method() {

    System.out.println("公用无参方法");

    }

    public void method(String name) {

    System.out.println("公用有参方法");

    }

    protected void method2(String name) {

    System.out.println("受保护有参方法");

    }

    private void method1() {

    System.out.println("私有无参方法");

    }

    public void OutStudent(int age,String name,String address){

    System.out.println("公用有参方法");

    System.out.println("学生信息:" + age + name + address);

    }

    然后具体使用方法如下:

    //加载Class对象

    Class c = Class.forName("demo.demo.Student");

    System.err.println("获取所有的public修饰的方法");

    Method[] methods = c.getMethods();

    for (Method method : methods) {

    System.out.println(method);

    }

    Thread.sleep(1000);

    System.err.println("获取所有的方法");

    Method[] methods1 = c.getDeclaredMethods();

    for (Method method:methods1

    ) {

    System.out.println(method);

    }

    Thread.sleep(1000);

    System.err.println("获取指定方法(不带参)并使用");

    Method method = c.getDeclaredMethod("method");

    System.out.println(method);

    Thread.sleep(1000);

    System.err.println("获取指定方法(带参)并使用");

    Method method1 = c.getMethod("method",String.class);

    System.out.println(method1);

    Thread.sleep(1000);

    System.err.println("获取指定方法(多个参数)并使用");

    Method method2 = c.getDeclaredMethod("OutStudent",int.class, String.class, String.class);

    //获取构造方法,实例化一个对象

    Object object = c.getConstructor().newInstance();

    //给指定方法传值

    //使用invoke调用指定方法

    method2.invoke(object,18,"kk","address");

    运行结果如下所示:

    相关文章

      网友评论

          本文标题:Java的反射机制

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