• java--反射


    一、反射的概述

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.


    以上的总结就是什么是反射
    反射就是把java类中的各种成分映射成一个个的Java对象
    例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
    如图是类的正常加载过程:反射的原理在与class对象。
    熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。

    二、Java中为什么需要反射?反射要解决什么问题?

    Java中编译类型有两种:

    • 静态编译:在编译时确定类型,绑定对象即通过。
    • 动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性。

    Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public、static等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

    Reflection可以在运行时加载、探知、使用编译期间完全未知的classes。即Java程序可以加载一个运行时才得知名称的class,获取其完整构造,并生成其对象实体、或对其fields设值、或唤起其methods。

    反射(reflection)允许静态语言在运行时(runtime)检查、修改程序的结构与行为。
    在静态语言中,使用一个变量时,必须知道它的类型。在Java中,变量的类型信息在编译时都保存到了class文件中,这样在运行时才能保证准确无误;换句话说,程序在运行时的行为都是固定的。如果想在运行时改变,就需要反射这东西了。

    实现Java反射机制的类都位于java.lang.reflect包中:

    1. Class类:代表一个类
    2. Field类:代表类的成员变量(类的属性)
    3. Method类:代表类的方法
    4. Constructor类:代表类的构造方法
    5. Array类:提供了动态创建数组,以及访问数组的元素的静态方法

    一句话概括就是使用反射可以赋予jvm动态编译的能力,否则类的元数据信息只能用静态编译的方式实现,例如热加载,Tomcat的classloader等等都没法支持。

    三、使用

    先创建一个对象

    package com.example.jdk8demo;
    
    import com.alibaba.fastjson.JSON;
    
    public class Student {
        private String name;
        private Integer age;
        private Status status;
    
        public String name1;
        public Integer age1;
    
        private String getName1(){
            return this.name1;
        }
    
        private String setName(String name){
            this.name = name;
            return "调用setName成功,设置为"+this.name;
        }
    
        private String setName1(String name){
            this.name1 = name;
            return "调用setName1成功,设置为"+this.name1;
        }
    
        public Student(String name,Integer age){
            this.name = name;
            this.age = age;
        }
    
        public Student(){
    
        }
    
        public Student(String name,Integer age, Status status){
            this.name = name;
            this.age = age;
            this.status = status;
        }
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public Status getStatus(){
            return status;
        }
    
    
    
        public enum Status{
            FREE,
            BUSY,
            VOCATION
        }
    
    }

    反射使用:

    (1)获取反射对象

    package com.example.jdk8demo;
    
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    @SpringBootTest
    @Slf4j
    class FanSheTest {
    
        @Test
        public void test() throws Exception{
            //获取反射对象
            Student student = new Student();
            Class studentClass1 = student.getClass();
            log.info("student.getClass()反射结果{}",studentClass1.getName());
            Class studentClass2 = Student.class;
            log.info("Student.class反射结果{}",studentClass2.getName());
            log.info("Student.class==student.getClass()结果{}",studentClass1==studentClass2);
            Class studentClass3 = Class.forName("com.example.jdk8demo.Student");
            log.info("Class.forName反射结果{}",studentClass3.getName());
            log.info("Student.class==Class.forName结果{}",studentClass3==studentClass2);
    }

     测试结果:

     由测试结果可见,三种方式得到的结果是一致的

    (2)获取相关内容

    //获取构造函数集合
            Constructor[] cons = studentClass1.getConstructors();
            log.info("反射获取所有构造函数{}", JSON.toJSONString(cons));
            //获取无参构造
            Constructor con = studentClass1.getConstructor();
            log.info("反射获取无参构造函数{}", JSON.toJSONString(con));
            //获取有参构造
            Constructor con1 = studentClass1.getConstructor(String.class, Integer.class);
            log.info("反射获取有参构造函数{}", JSON.toJSONString(con));
    
            //获取公有字段,此处字段必须是public修饰,否则会报错
            Field field = studentClass1.getField("name1");
            log.info("公有字段{}", JSON.toJSONString(con));

    (3)动态调用方法

            //获取私有方法
            Method setName1 = studentClass1.getDeclaredMethod("setName1", String.class);
            setName1.setAccessible(true);
            String s = (String)setName1.invoke(Student.class.newInstance(),"lcl");
            log.info("========={}", s);
    
            //获取公有方法
            Method setName = studentClass1.getDeclaredMethod("setName", String.class);
            String ss = (String)setName1.invoke(Student.class.newInstance(),"mm");
            log.info("========={}", ss);

    测试结果:

     这里需要特别说明,如果动态调用的是私有方法,则需要使用 setName1.setAccessible(true);  进行解绑操作,才可以使用invoice方法调用。

    声明:本文根据https://blog.csdn.net/grandgrandpa/article/details/84832343写的,里面大量复制内容,感谢博主

  • 相关阅读:
    剑指Offer-二叉搜索树与双向链表
    剑指Offer-数组中只出现一次的数字
    剑指Offer-栈的压入、弹出序列
    剑指Offer-反转链表
    剑指Offer-和为S的两个数字
    剑指Offer-数字在排序数组中出现的次数
    剑指Offer-二叉树的下一个结点
    Notepad++中实现Markdown语法高亮与实时预览
    centos7安装activemq5.15
    博客园展示音频视频
  • 原文地址:https://www.cnblogs.com/liconglong/p/13036388.html
Copyright © 2020-2023  润新知