反射枚举

1、定义

java的反射机制是在运行状态中,对于任意一个类,都能直到这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意方法和属性,既然能够拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

2、用途

*在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用java的反射机制通过反射来获取所需的私有成员或方法

*反射最重要的用途是开发各种通用框架,比入我们在Spring中,我们将所有的类Bean交给Spring容器进行管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的基本信息,Spring就是根据这些信息,需要创建哪些Bean,Spring就动态的创建这些类。

3、反射的基本信息

java程序中血多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,例如Person p=new Student();这句代码中p在编译时类型为Person,运行时为Student。程序需要在运行时发现对象和类的真实信心,而通过使用反射程序就能判断出该对象和类属于哪些类。

4、反射相关的类

 4.1、Class的反射机制

 4.2、获取类对象的三种方式

在反射之前,我们需要做的第一步就是先拿到当前需要反射类的对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意方法和属性,既然能拿到,那么,就可以修改部分类型信息

第一种:使用Class.forName("类的全路径名");静态方法

第二种:使用.Class方法

第三种:使用类对象的getClass()方法

示例:


/**
 * 获取类对象方式
 */
public class Reflection01 {
    public static void main(String[] args) {
        //1、通过类来获取
        Class<Student> studentClass=Student.class;
        //2、通过实例对象来获取
        Student student=new Student();
        Class<? extends Student> classByInstance=student.getClass();
        Class<?> classByReflect=null;
        try {
            //通过反射来获取
            classByReflect=Class.forName("Day20221201.Test11.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //判断这三个对象是否是同一个对象
        System.out.println("===========使用==判断是否相等============");
        System.out.println(studentClass==classByReflect);
        System.out.println(classByReflect==classByInstance);
        System.out.println(studentClass==classByInstance);
        System.out.println("===========使用equals()判断是否相等============");
        System.out.println(studentClass.equals(classByReflect));
        System.out.println(classByReflect.equals(classByInstance));
        System.out.println(classByInstance.equals(studentClass));
    }
}

 

4.3、反射的使用


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Reflection02 {
    /**
     * 通过反射创建一个新的实例对象
     */
    public static void reflectNewInstance(){
        System.out.println("========通过反射创建一个新的实例对象==========");
        try {
            //1、获取类对象
            Class<?> clazz=Class.forName("Day20221201.Test11.Student");
            System.out.println(clazz.getName());
            //2、通过类对象创建一个新的实例对象
            Student student= (Student) clazz.newInstance();
            student.setAge(18);
            //打印一下
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过反射操作构造方法
     */
    public static void reflectConstructor(){
        System.out.println("=========通过反射操作构造方法=========");
        try {
            //1、获取类对象
            Class<?> clazz=Class.forName("Day20221201.Test11.Student");
            //2、通过类对象获取构造方法
            //Constructor<?>[] constructors=clazz.getConstructors();//可以获得到所有public权限的构造方法
            Constructor<?>[] constructors=clazz.getDeclaredConstructors();//获取已经定义的构造方法,包括私有的
            for (int i = 0; i < constructors.length; i++) {
                System.out.println(constructors[i]);
            }
            //3、获取一个指定的构造方法
            Constructor<?> constructor=clazz.getConstructor();
            //4、通过构造方法创建一个新的实例对象
            Student student= (Student) constructor.newInstance();
            System.out.println(student);
            student.setName("鸡你太美");
            System.out.println(student);
            //5、调用私有的,多个参数的构造方法去创建对象
            Constructor<?> constructor1=clazz.getDeclaredConstructor(String.class,int.class);
            //修改私有方法的访问权限
            constructor1.setAccessible(true);
            Student student1= (Student) constructor1.newInstance("咯咯",18);
            System.out.println("通过私有构造方法创建的对象:"+student1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过反射操作属性
     */
    public static void reflectField(){
        System.out.println("========通过反射操作属性========");
        try {
            //1、获取类对象
            Class<?> clazz=Class.forName("Day20221201.Test11.Student");
            //2、获取所有发生的数组
            //所有访问权限为public的属性
            //Field[] fields=clazz.getFields();
            //获取所有访问权限或所有定义的属性
            Field[] fields=clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                System.out.println(fields[i]);
            }
            //创建一个对象
            Student student= (Student) clazz.newInstance();
            System.out.println(student);
            //操作这个属性
            //先获取一个属性
            Field fieldAge=clazz.getField("age");
            //给这个属性设置一个值
            fieldAge.set(student,18);
            System.out.println(student);
            //获取私有属性并赋值
            Field fieldName=clazz.getDeclaredField("name");
            //修改访问权限
            fieldName.setAccessible(true);
            fieldName.set(student, "只因坤坤爱坤坤");
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
    public static void reflectMethod(){
        System.out.println("=======通过反射操作方法========");
        try {
            //1、创建类对象
            Class<?> clazz=Class.forName("Day20221201.Test11.Student");
            //2、获取所有方法信息
            //所有访问修饰符为public的方法
            //包括父类的方法都可以获取到
            //Method[] methods=clazz.getMethods();
            Method[] methods=clazz.getDeclaredMethods();
            for (Method items:methods) {
                System.out.println(items);
            }
            //创建一个实例对象
            Student student= (Student) clazz.newInstance();
            //通过指定对象获取去获取一个指定的量
            Method methodSleep=clazz.getDeclaredMethod("sleep");
            methodSleep.invoke(student);
            //调用一个私有的量
            Method methodFunction=clazz.getDeclaredMethod("function",String.class);
            //修改访问权限
            methodFunction.setAccessible(true);
            methodFunction.invoke(student,"通过·反射传入的参数");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        // 通过反射创建一个新的实例对象
        reflectNewInstance();
        // 通过反射操作构造方法
        reflectConstructor();
        // 通过反射操作属性
        reflectField();
        // 通过反射操作方法
        reflectMethod();
    }
}

 

5、反射的优点和缺点

优点:

*对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法

*增加程序的灵活性和扩展性,降低耦合性,提高自适应能力

*反射已经应用在了很多流行的框架如:Spring、Structs等等

缺点:

*使用反射会有效率问题。会导致程序效率降低

*反射技术绕过了源代码技术,因而会带来维护问题。反射代码比相应的代码更加复杂

7、枚举的使用

枚举是在JDK1.5之后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式

public static  final int RED = 1;
public static  final int GREEN = 2;
public static  final int BLACK = 3;

但是常量列举有不好的地方,例如:可能碰巧有个数字1,但是它误以为是RED,现在我们可以直接用枚举类型来进行组织,这样一来,就拥有了类型——枚举类型,而不是普通的整型1;

public enum TestEnum {
  RED,BLACK,GREEN;
}

优点:将常量组织起来统一进行管理

应用场景:错误状态码,消息类型,颜色划分,状态机等等

8、使用

8.1、switch语句


public class Enum01 {
    public static void main(String[] args) {
        int color=1;
        switch(color){
            case 1:
                System.out.println("这是红色");
                break;
            case 2:
                System.out.println("这是黄色");
                break;
            case 3:
                System.out.println("这是蓝色");
                break;
            case 4:
                System.out.println("这是绿色");
                break;
        }
        int a=10;
        int b=20;
        System.out.println(sum(a,b));
        System.out.println(sum(a,color));
    }

    private static int sum(int x, int y) {
        return x+y;
    }
}

 

8.2、Enum的常用方法

 8.3、示例

先定义枚举类型


public enum ColorEnum {
    RED,GREEN,BLACK,WHITE;
}

public enum ResultEnum {
    SUCCESS(200,"成功"),
    ERROR_CLIENT(400,"客户端出错了"),
    ERROR_SERVER(500,"服务器出错了"),
    NONE(-99999,"未定义");
    private int code;
    private String message;

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    ResultEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }

    @Override
    public String toString() {
        return "ResultEnum{" +
                "code=" + code +
                ", message='" + message + '\'' +
                '}';
    }
    public ResultEnum valueOf(int Code){
        switch(code){
            case 200:
                return SUCCESS;
            case 400:
                return ERROR_CLIENT;
            case 500:
                return ERROR_SERVER;
        }
        return NONE;
    }
}

public class Enum02 {
    public static void main(String[] args) {
        ColorEnum colorEnum=ColorEnum.WHITE;
        switch (colorEnum){
            case RED:
                System.out.println("鸡你太美");
                break;
            case GREEN:
                System.out.println("唱跳、rap、篮球");
                break;
            case BLACK:
                System.out.println("小黑子");
                break;
            case WHITE:
                System.out.println("中分头、背带裤,我叫坤坤你记住");
                break;
        }
    }
}


public class Enum03 {
    public static void main(String[] args) {
        ResultEnum resultEnum=ResultEnum.SUCCESS;
        System.out.println("状态码:"+resultEnum.getCode()+",描述;"+resultEnum.getMessage());
        ResultEnum resultEnum1=ResultEnum.NONE;
        System.out.println("状态码:"+resultEnum1.getCode()+",描述;"+resultEnum1.getMessage());
    }
}

 

 


public class Enum04 {
    public static void main(String[] args) {
        //value()方法演示
        ResultEnum[] values=ResultEnum.values();
        for (ResultEnum items:values) {
            System.out.println(items);
        }
        //valueOf方法演示
        ResultEnum resultEnum=ResultEnum.valueOf("ERROR_CLIENT");
        System.out.println("状态码:"+resultEnum.getCode()+",描述:"+resultEnum.getMessage());
        //CompareTo()方法比较
        System.out.println(ResultEnum.SUCCESS.compareTo(ResultEnum.ERROR_CLIENT));
        System.out.println(ResultEnum.SUCCESS.compareTo(ResultEnum.SUCCESS));
        //ordinal()方法
        System.out.println("========================");
        for (int i = 0; i < values.length; i++) {
            System.out.println("枚举:"+values[i]+",ordinal:"+ values[i].ordinal());
        }
    }
}

 


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Enum05 {
    //通过反射创建一个枚举
    public static void main(String[] args) {
        try {
            //获取类对象
            Class<?> clazz=Class.forName("Day20221201.Test11.ResultEnum");
            Constructor[] constructors=clazz.getDeclaredConstructors();
            for (int i = 0; i < constructors.length; i++) {
                System.out.println(constructors[i]);
            }
            //获取构造方法
            Constructor<?> constructor=clazz.getDeclaredConstructor(String.class,int.class,int.class,String.class);
            //修改访问权限
            constructor.setAccessible(true);
            Object o = constructor.newInstance("ERROR_NETWORK", 4, 600, "网络错误");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

 9、结论:

针对Enum05的结果,可以确定不能通过new或是反射去创建一个枚举对象,所以我们认为枚举是比较安全的,利用反射性可以实现一个单例模式的类(单例模式就是全局唯一,只有一个对象)

*枚举本身就是一个类,其构造方法默认是私有的,且都继承于java.long.Enum

*枚举可以避免反射和序列化问题

*便于让我们把常量组织起来,统一管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25545.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软考A计划-电子商务设计师-计算机系统基础知识

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Delphi11的多线程ⓞ,附送图片处理代码

Delphi11的多线程ⓞ OLD Coder , 习惯使用Pascal 接下来准备启用多线程&#xff0c;毕竟硬件多核&#xff0c;Timer不太爽了&#xff08;曾经的桌面&#xff0c;都是Timer——理解为“片”&#xff09; 突然想写写&#xff0c;不知道还有多少D兄弟们在。 从源码开始 用D11之…

mybatisplus递归传递多个参数 | mybatisplus传递多个参数获取层级数据 | mybatisplus传递多个参数获取树形数据

搜索关键字&#xff1a; mybatisplus关联查询传递参数|"select""树形结构"|"select""树形结构""传参"| "select""many""传参"| "select""column""传参" 1、…

内置工具横向移动

IPCSchtasks IPC: IPC$是共享"命令管道"的资源&#xff0c;它是为了让进程通信而开放的命名管道&#xff0c;连接双方可以建立安全的通道并以此通道进行加密数据交换&#xff0c;从而实现对远程计算机的访问。 利用条件&#xff1a; 1、开放139、445 2、目标开启…

SAP-MM-采购申请审批那些事!

1、ME55不能审批删除行项目的PR 采购申请审批可以设置行项目审批或抬头审批。如果设置为抬头审批时&#xff0c;ME55集中审批时&#xff0c;就会发现有些采购申请时不能审批的&#xff0c; 那么这些采购申请时真的不需要审批么&#xff1f;不是的&#xff0c;经过核对这些采购申…

【每周一书】--(认知觉醒)思考:如何用清爽的情绪面对内卷的当下?

【每周一书】--&#xff08;认知觉醒&#xff09;思考&#xff1a;如何用清爽的情绪面对内卷的当下&#xff1f; 认知觉醒&#xff1a;开启自我改变的原动力焦虑&#xff1a;焦虑的根源完成焦虑定位焦虑选择焦虑环境焦虑难度焦虑 如何拥有清爽的情绪&#xff0c;释放焦虑情绪 认…

STM32F407单片机HAL库CAN2不能接收数据解决方法

最近在使用stm32F407的片子调试can通信&#xff0c;直接在正点原子的代码上修改调试&#xff0c;调试can1的时候&#xff0c;基本没啥问题&#xff0c;收发都正常&#xff0c;使用查询模式和中断模式都可以。但是当修改到can2的时候&#xff0c;可以正常发送数据&#xff0c;但…

WPF 热重载失效了

关于 热重载官方说明&#xff1a; WPF 和 UWP 应用的 XAML 热重载是什么Introducing the .NET Hot Reload experience for editing code at runtime 热重载简单来说&#xff0c;就是点击运行程序后&#xff0c;修改 XAML 代码&#xff0c;应用程序会实时的显示你的修改 为…

Python入门(十三)函数(一)

函数&#xff08;一&#xff09; 1.函数概述2.函数定义2.1向函数传递信息2.2实参和形参 作者&#xff1a;xiou 1.函数概述 函数是带名字的代码块&#xff0c;用于完成具体的工作。要执行函数定义的特定任务&#xff0c;可调用该函数。需要在程序中多次执行同一项任务时&#…

中间件SOME/IP简述

SOME/IP SOME/IP 不是广义上的中间件&#xff0c;严格的来讲它是一种通信协议&#xff0c;但中间件这个概念太模糊了&#xff0c;所以我们也一般称 SOME/IP 为通信中间件。 SOME/IP 全称是 Scalable service-Oriented MiddlewarE over IP。也就是基于 IP 协议的面向服务的可扩…

使用Python绘制M2货币供应率曲线

M2广义货币供应量&#xff1a;流通于银行体系之外的现金加上企业存款、居民储蓄存款以及其他存款&#xff0c;它包括了一切可能成为现实购买力的货币形式&#xff0c;通常反映的是社会总需求变化和未来通胀的压力状态。近年来&#xff0c;很多国家都把M2作为货币供应量的调控目…

ChatGPT国内免费使用方法【国内免费使用地址】

当下人工智能技术的快速发展&#xff0c;聊天机器人成为了越来越多人们日常生活和工作中的必备工具。如何在国内免费使用ChatGPT聊天机器人&#xff0c;成为了热门话题。本文将为你详细介绍ChatGPT国内免费使用方法&#xff0c;让你轻松拥有聊天机器人助手&#xff0c;提高工作…

Vue3 小兔鲜:Pinia入门

Vue3 小兔鲜&#xff1a;Pinia入门 Date: May 11, 2023 Sum: Pinia概念、实现counter、getters、异步action、storeToRefs保持响应式解构 什么是Pinia Pinia 是 Vue 的专属状态管理库&#xff0c;可以实现跨组件或页面共享状态&#xff0c;是 vuex 状态管理工具的替代品&…

论文学习笔记:Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

论文阅读&#xff1a;Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 今天学习的论文是 ICCV 2021 的 best paper&#xff0c;Swin Transformer&#xff0c;可以说是 transformer 在 CV 领域的一篇里程碑式的工作。文章的标题是一种基于移动窗口的…

C++异步调用方法

C之future和promise future和promise的作用是在不同线程之间传递数据。使用指针也可以完成数据的传递&#xff0c;但是指针非常危险&#xff0c;因为互斥量不能阻止指针的访问&#xff1b;而且指针的方式传递的数据是固定的&#xff0c;如果更改数据类型&#xff0c;那么还需要…

代码随想录算法训练营第四十六天|139.单词拆分、关于多重背包,你该了解这些!、背包问题总结篇!

文章目录 一、139.单词拆分二、关于多重背包&#xff0c;你该了解这些&#xff01;三、背包问题总结篇&#xff01;总结 一、139.单词拆分 public boolean wordBreak(String s, List<String> wordDict) {//完全背包问题&#xff0c;因为可以重复&#xff0c;背包正序排列…

ROS:ROS是什么

目录 一、ROS简介二、ROS可以做些什么三、ROS特征四、ROS特点4.1点对点设计4.2不依赖编程语言4.3精简与集成4.4便于测试4.5开源4.6强大的库与社区 五、ROS的发展六、ROS架构6.1OS层6.2中间层6.3应用层 七、通信机制八、计算图8.1节点&#xff08;Node&#xff09;8.2节点管理器…

FastReport.Net FastReport.Core 2023.2.15 Crack

快速报告.NET .NET 7 的报告和文档创建库 FastReport.Net & FastReport.Core适用于 .NET 7、.NET Core、Blazor、ASP.NET、MVC 和 Windows 窗体的全功能报告库。它可以在 Microsoft Visual Studio 2022 和 JetBrains Rider 中使用。 快速报告.NET 利用 .NET 7、.NET Core、…

从零开始学习JVM(六)-直接内存和执行引擎

1 直接内存介绍 直接内存不是虚拟机运行时数据区的一部分&#xff0c;也不是《Java虚拟机规范》中定义的内存区域。直接内存是在Java堆外的、直接向系统申请的内存空间。直接内存来源于NIO&#xff0c;通过存在堆中的DirectByteBuffer操作Native内存。通常访问直接内存的速度会…

在 Linux 中启动时自动启动 Docker 容器的 2 种方法

Docker 是一种流行的容器化平台&#xff0c;允许开发人员将应用程序及其依赖项打包成一个独立的容器&#xff0c;以便在不同环境中运行。在 Linux 系统中&#xff0c;我们可以通过配置来实现在系统启动时自动启动 Docker 容器。本文将详细介绍两种方法&#xff0c;以便您了解如…