注解与反射

news2024/11/24 11:55:51

1、注解(Annotation


1.1、何为注解?

注解(Annotation)是从JDK5.0开始引入的技术,以@注解名在代码中存在,例如:

  • @Override:限定重写父类方法,该注解只能用于方法
  • @Deprecated:用于表示所修饰的元素(类,方法)已过时
  • @SuppressWarnings:抑制编译器警告(镇压警告)

Annotation可以像修饰符一样被使用,可用于修饰包、类、构造器、成员变量、参数、局部变量的声明,还可添加一些参数值

1.2、注解与注释

注解也可以看做是一种注释,通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。但是,注解,不同于单行注释和多行注释

  • 对于单行注释和多行注释是给程序员看的
  • 而注解是可以被编译器或其他程序读取的。程序还可以根据注解的不同,做出相应的处理

10.3、注解的重要性

在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置

注解是大势所趋,框架 = 注解 + 反射 + 设计模式

10.4、自定义注解

public @interface MyAnnotation {
    String value() default "hello world";
}

特殊属性

  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
  • 但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的

10.5、元注解

元注解:对现有的注解进行解释说明的注解

  • Target:约束自定义注解只能在哪些地方使用
  • Retention:申明注解的生命周期
  • Documented:表示所修饰的注解在被javadoc解析时,保留下来
  • Inherited:被它修饰的Annotation将具备继承性
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface MyAnnotation {
    String value() default "hello world";
}

@Target中可使用的值定义在ElementType枚举类中,常用值如下:

  • TYPE:类,接口
  • FIELD:成员变量
  • METHOD:成员方法
  • PARAMETER:方法参数
  • CONSTRUCTOR:构造器
  • LOCAL_VARIABLE:局部变量

@Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下:

  • SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

2、反射(reflection


2.1、何为反射?

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分

在运行时,可以直接得到这个类的构造器对象:Constructor

在运行时,可以直接得到这个类的成员变量对象:Field

在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制

反射的关键:反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分

反射的作用:

  • 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
  • 结合配置文件,动态的创建对象并调用其方法

2.2、获取class对象三种方式

在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException {
    // 全类名 = 包名 + 类名
    // 第一种方式:最为常用
    Class clazz1 = Class.forName("com.zhang.Student");
    System.out.println(clazz1);

    // 第二种方式:一般当做参数传递
    Class<Student> clazz2 = Student.class;

    // 第三种方式:必须有了该类之后,才可获取使用
    Student stu = new Student();
    Class<? extends Student> clazz3 = stu.getClass();
    System.out.println(clazz1 == clazz2);       // true
    System.out.println(clazz2 == clazz3);       // true
}

2.3、反射获取构造方法

获取构造器的方法

方法说明
Constructor<?>[] getConstructors()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[] getDeclaredConstructors()返回所有构造器对象的数组,存在就能拿到
Constructor<T> getConstructor(Class<?>… parameterTypes)返回单个构造器对象(只能拿public的)
Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造器对象,存在就能拿到

Constructor类中用于创建对象的方法

符号说明
T newInstance(Object… initargs)根据指定的构造器创建对象
public void setAccessible(boolean flag)设置为true,表示取消访问检查,进行暴力反射
public static void main(String[] args) throws Exception {
    // 获取字节码文件的对象
    Class<?> clazz = Class.forName("com.zhang.Student");
    // 获取所有公共的构造方法
    /* Constructor<?>[] cons = clazz.getConstructors();
    for (Constructor<?> con : cons) {
        System.out.println(con);
    } */

    // 获取所有的构造方法(包括私有)
    /* Constructor<?>[] dc = clazz.getDeclaredConstructors();
    for (Constructor<?> d : dc) {
        System.out.println(d);
    } */

    // 获取空参构造
    Constructor con1 = clazz.getDeclaredConstructor();
    System.out.println(con1);

    // 获取一个参数的构造(参数类型是String的)
    Constructor<?> con2 = clazz.getDeclaredConstructor(String.class);
    System.out.println(con2);

    // 获取二个参数的构造(参数类型是String、int的)
    Constructor<?> con3 = clazz.getConstructor(String.class, int.class);
    System.out.println(con3);

    // 临时取消权限校验(暴力反射)
    con2.setAccessible(true);
    Student stu = (Student) con2.newInstance("小昭");
    System.out.println(stu);
}

2.4、反射获取成员变量

public static void main(String[] args) throws Exception {
    // 获取字节码文件的对象
    Class<?> clazz = Class.forName("com.zhang.Student");
    // 获取所有公共的成员变量
    /* Field[] fields = clazz.getFields();
    for (Field field : fields) {
        System.out.println(field);
    } */

    // 获取所有成员变量(包括私有)
    /* Field[] dfs = clazz.getDeclaredFields();
    for (Field field : dfs) {
        System.out.println(field);
    } */

    // 获取指定的成员变量(公共的)
    Field address = clazz.getField("address");
    System.out.println(address);

    // 获取指定的成员变量(公共私有)
    Field name = clazz.getDeclaredField("name");
    System.out.println(name.getName());

    // 获取成员变量的类型
    System.out.println(name.getType());

    Student s1 = new Student("小黑", 22, "河南-郑州");

    // 暴力反射
    name.setAccessible(true);
    // 获取成员变量的值
    String value = (String) name.get(s1);
    System.out.println(value);

    // 修改对象中的值
    name.set(s1, "小白");

    System.out.println(s1);
}

2.5、反射获取成员方法

public static void main(String[] args) throws Exception {
    Class<?> clazz = Class.forName("com.zhang.Student");
    // 获取所有公共的成员方法(包括父类)
    // Method[] methods = clazz.getMethods();
    // for (Method method : methods) {
    //     System.out.println(method);
    // }

    // 获取所有成员方法(包括本类私有,不包括父类)
    // Method[] dm = clazz.getDeclaredMethods();
    // for (Method method : dm) {
    //     System.out.println(method);
    // }

    // 获取指定成员方法(公共的)
    Method getName = clazz.getMethod("getName");
    System.out.println(getName);

    // 获取指定成员方法(公共私有)
    Method hello = clazz.getDeclaredMethod("sayHello", String.class);
    System.out.println(hello);

    // 获取方法名
    System.out.println(hello.getName());        // sayHello

    // 获取方法参数个数
    System.out.println(hello.getParameterCount());      // 1

    // 获取方法抛出的异常
    Class<?>[] ets = hello.getExceptionTypes();
    for (Class<?> ex : ets) {
        System.out.println(ex);
    }

    // 调用成员方法
    // 暴力反射
    hello.setAccessible(true);
    Student s1 = new Student("晓琳", 22, "北京-海淀");
    String res = (String) hello.invoke(s1, s1.getName());
    System.out.println(res);

    // 获取方法的返回值
    System.out.println(hello.getReturnType());      // java.lang.String
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Word控件Spire.Doc 【文本框】教程(5): 插入、读取和删除表格

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

提问超时~Zabbix Meetup成都站棒在哪里?

图片 2023年5月13日&#xff0c;迎着初夏灿烂的阳光&#xff0c;Zabbix Meetup首次在成都举办。本次活动吸引了来自Zabbix社区用户、合作伙伴等约50余位伙伴热情参与&#xff0c;倾听来自原厂培训师、社区资深用户们关于Zabbix的精彩内容分享。还有定制周边礼品和晚宴深入交流…

防火墙之iptables

防火墙之iptables 一.iptables概述 Linux 系统的防火墙 &#xff1a;IP信息包过滤系统&#xff0c;它实际上由两个组件netfilter 和 iptables组成。 主要工作在网络层&#xff0c;针对IP数据包。体现在对包内的IP地址、端口、协议等信息的处理上。二.netfilter/iptables 关系…

《终身成长》笔记二——失败挫折的意义

目录 经典摘录 思维模式改变了失败的意义/如何看待失败与成功 思维模式与抑郁症 努力后还是失败的事实会让自己找不到借口&#xff0c;是固定型思维模式者们最大的恐惧 问与答 经典摘录 思维模式改变了失败的意义/如何看待失败与成功 《纽约时报》上的一篇文章指出的&…

学生档案管理系统(SpringBoot,SSM,Maven,H-UI,Mysql)

【项目功能介绍】 本系统包含学生,后台管理员二种角色的用户 学生的功能包含: 登录,退出,修改密码,用户信息查看与修改,首页信息展示,轮播图,栏目及栏目文章列表,我的课程,我的课表,我的成绩,意见反馈,我的意见反馈。 后台管理员的功能包含: 登录,退出,修改密码,管理员管理,…

【计算机组成原理】实验一

文章目录 实验一 数据传送实验1. 实验目的2. 实验仪器3. 原理概述4. 实验内容步骤4.1 手动实验环境的建立4.2 手控传送实验 5. 实验结论及问题讨论 实验一 数据传送实验 1. 实验目的 2. 实验仪器 3. 原理概述 4. 实验内容步骤 4.1 手动实验环境的建立 1)初始待令状态 上电或…

监控kafka topic,钉钉报警

1、需求的诞生 前几天公司我们部门需要演示一个应用&#xff0c;应用依赖kafka的数据&#xff0c;但是kafka的数据来自其他部门的投递。 一些原因导致数据无法给到&#xff0c;导致我们部门的演示也很有问题&#xff0c;所以想做一个简单的kafka topic的监控&#xff0c;在没…

内网渗透之权限维持-黄金白银票据隐藏账户远控-RustDeskGotoHTTP

0x01权限维持-隐藏用户 CreateHiddenAccount工具 CreateHiddenAccount -u test -p Psswrd用户管理能查看到&#xff0c;命令查看看不到&#xff0c;单机版无法删除(不在任何组)&#xff0c;域环境(在administrator组中)可以删除 0x02权限维持-黄金白银票据 ⻩⾦票据⽣成攻…

捷威信keithley吉时利2410数字源表 销售回收KEITHLEY2470新款源表

吉时利Keithley 2410 /2470高压源表/数字源表 产品概览 Keithley 2410 高压源表专为需要紧密耦合源和测量的测试应用而设计。Keithly 2410 提供精密电压和电流源以及测量功能。它既是高度稳定的直流电源&#xff0c;又是真正的仪器级 5-1/2 数字万用表。电源特性包括低噪声、…

three.js实现拖拽生成模型场景

THREE.js 可以实现很多web 3D的效果&#xff0c;最近想实现一个拖拽生成场景的功能&#xff0c;主要用到拖拽API,draggable 的几个事件来实现&#xff0c;拖拽模型时记录模型属性&#xff0c;释放到画布时生成当前屏幕坐标对应的焦点上&#xff0c;最后生成模型。 <!DOCTYP…

增量更新和原始快照

三色标记法 2.1 基本算法 要找出存活对象&#xff0c;根据可达性分析&#xff0c;从GC Roots开始进行遍历访问&#xff0c;可达的则为存活对象&#xff1a; 最终结果&#xff1a;A/D/E/F/G 可达 我们把遍历对象图过程中遇到的对象&#xff0c;按“是否访问过”这个条件标记成…

【LeeCode】每日一题:复制带随机指针的链表

​&#x1f47b;内容专栏&#xff1a;《LeetCode刷题专栏》 &#x1f428;本文概括&#xff1a; 138.复制带随机指针的链表 &#x1f43c;本文作者&#xff1a;花 碟 &#x1f438;发布时间&#xff1a;2023.5.18 ​复制带随机指针的链表 力扣链接-> 138.复制带随机指针的链…

VS2019新建WebService/Web服务/asmx并通过IIS实现发布和调用

场景 对接第三方系统提供接口文档中显示为asmx接口 访问接口返回数据格式为 xml中的数据格式为json数据。 需要在本地新建并模拟调试环境。 注&#xff1a; 博客&#xff1a;霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主 实现 1、WebService WebService…

LeetCode刷题 --- 链表

定义一个node节点 class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val val;}ListNode(int val, ListNode next) {this.val val;this.next next;} } 206 反转链表 题目&#xff1a;给你单链表的头节点 head &#xff0c;请你反转链表&#x…

【FAQ】视频编辑服务常见问题及解答

Q1问题描述 1、 访问贴纸等素材的时候提示“网络异常&#xff0c;请重试”怎么办&#xff1f; 2、 使用AI能力时&#xff0c;提示“errorCode:20124 errorMsg:Method not Allowed”&#xff1f; 解决方案 请做以下检查&#xff1a; 1、 在代码中检查鉴权信息是否已设置。如…

AI法律助手:ChatGPT如何提供智能化解决方案

日常生活中&#xff0c;民事纠纷不可避免&#xff0c;涉及到多种问题&#xff0c;如合同纠纷、劳动纠纷、婚姻家事、民间借贷、交通事故、工伤赔偿、房屋租赁等。解决这些问题&#xff0c;需要花费大量时间和精力&#xff0c;但现在&#xff0c;我们有了一种全新的解决方案&…

蓝库云:建立智慧零售,零代码技术能起到什么作用

随着科技的进步更多智能化的技术及应用融入我们生活中&#xff0c;例如零售行业在现代零售和传统零售的区别不仅在于营销策略、销售方式、销售渠道以及运营模式等方面&#xff0c;更多是在现代零售则更注重数字化营销&#xff0c;发挥社交媒体和电子商务渠道的作用&#xff0c;…

“前端”工匠系列(二):合格的工匠,怎么做好价值落地 | 京东云技术团队

一、“技术鄙视链&#xff1f;” 如果你是一个技术人&#xff0c;相信都知道技术圈有个相互的鄙视链&#xff0c;这个链条从技术人自己认知的角度在以业务价值为中心嵌套的一层一层的环&#xff0c;就像洋葱&#xff0c;具体的描述这里不赘述了。 出门左拐随便抓住一个人问一…

RabbitMQ应用问题——消息补偿机制以及代码示例

RabbitMQ应用问题——消息补偿机制以及代码示例 RabbitMQ应用问题 消息可靠性的保障 消息补偿机制 详细说明 这里使用了简单的代码进行演示&#xff0c;订单的消费者没有写&#xff0c;在订单的消费同时&#xff0c;发送一条增加积分消息到积分队列。 详细流程途中都有注明…

STM32+ov7725+ESP8266实现无线图传-完成上位机图像显示

一、需求 stm32f407探索者开发板和STM32F103ZET6战舰开发板。接正点原子ov5640、OV7725、OV2640摄像头,通过esp8266Wi-Fi模块(透传模式)将摄像头采集到的rgb565格式图片通过tcp/ip协议上传到上位机显示。 二、设计思路 【1】使用QT开发上位机,建立TCP服务器,接收ESP8266…