00-JAVA基础-注解及反射解析注解

注解

什么是注解

Java 注解(Annotation)是 JDK 5.0 引入的一种元素,用于为 Java 代码提供元数据。元数据是关于数据的数据,它为代码提供附加信息,而这些信息并不直接参与到程序的逻辑中,但可以被编译器或其他工具使用。注解本身对代码的逻辑没有任何影响,但可以通过反射机制读取注解信息,从而执行相应的操作。

注解的作用

  • 不是程序本身,可以对程序作出解释
  • 可以被其他程序(如:编译器等)读取。注解可以通过反射对其进行解释处理,这个是注解与注释的最大区别。
    如果一个注解没有通过反射进行注解信息处理,那么这个注解毫无意义。

注解的格式

注解是以 “@注释名” 在代码中存在的,还可以添加一下参数值,例如:@SuppressWarnings({“unchecked”, “rawtypes”})

注解的使用范围

注解可以附加在package,class,method,field等上面,相当于给他们添加了额为的辅助信息,我们可以通过反射机制变成实现对这些元素的访问。

注解的分类

Java 注解可以分为以下三种类型:

  • 标记注解:没有任何属性的注解,如 @Override。
  • 单值注解:只有一个属性的注解,如 @Deprecated(“不建议使用”)。
  • 完整注解:包含多个属性的注解,如 @SuppressWarnings({“unchecked”, “rawtypes”})。

Java 的内置注解包括:

  • @Override:表示当前方法是重写了父类的方法。
  • @Deprecated:表示某个类或方法已经过时,不建议使用。
  • @SuppressWarnings:用于告诉编译器忽略指定的警告。

除了内置注解,Java 还允许开发者自定义注解。

如何自定义注解

使用@interface自定义注解是,自动继承了java.lang.annotation.Annotation接口

格式

public @interface 注解名{定义体}

示例:声明一个MyAnnotation注解,包含value(默认值 “”)、number(默认值 0)两个参数

public @interface MyAnnotation {  
    String value() default "";  
    int number() default 0;  
}

其中的每一个方法实际上是声明了一个配置参数。

  • 方法名称就是参数的名称
  • 返回值类型就是参数的类型(返回值类型只能是基本数据类型,Class,String,enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value

注意:

源代码中我们经常看见在注解上还有一些注解例如,以下示例:
其中@Target与@Retention称之为元注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

什么是元注解

元注解(Meta-Annotation)是用于定义其他注解的注解。在Java中,注解是一种为代码提供元数据的机制,而元注解则是对这些注解进行进一步描述的工具。JDK中定义了四种标准的元注解类型:@Target、@Retention、@Documented和@Inherited。

  • @Target:用于指定注解的作用目标,例如类、方法、字段等。
所修饰范围取值ElementType
packagePACKAGE
类、接口、枚举、Annotation类型TYPE
类型成员(方法、构造方法、成员变量、枚举)CONSTRUCTOR:用于描述构造器
FIELD:用于描述字段
METHOD:用于描述方法
方法参数和本地变量LOCAL_VARIABLE:用于描述局部变量
PARAMETER:用于描述参数
  • @Retention:表示需要在什么级别保存该注释信息,用于指定注解的生命周期,即注解在何时生效,包括SOURCE(源码时有效)、CLASS(编译时有效)和RUNTIME(运行时有效)三种。
取值RetentionPolicy作用
SOURCE在源文件中有效
CLASS在class文件中有效
RUNTIME在运行时有效,为Runtime可以被反射机制读取
  • @Documented:用于指定将该注解包含在javadoc中。
  • @Inherited:用于指定子类可以继承父类中的注解。

在自定义注解时,通常需要使用元注解来定义注解的属性、行为以及作用范围等。
通过元注解,开发者可以更加灵活地控制注解的使用和效果,从而实现更高级的功能。

元注解使用案例

使用@Target设置注解的作用目标是方法,则注解放在类上是就会报错.

MyAnnotation.java

package demo1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
public @interface MyAnnotation {
}

AnnotationDemo.java

package demo1;

@MyAnnotation
public class AnnotationDemo {

    @MyAnnotation
    private void test(){}
}

编译结果:

在这里插入图片描述

反射机制读取注解

做一个简单User数据表与实体关系映射,通过反射解析创建生成表SQL

实体字段表字段备注
idint(10)主键
namevarchar2(30)-

表注解Table.java

package demo2.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 表名
 *
 * @author Anna.
 * @date 2024/4/4 21:41
 */
@Target(ElementType.TYPE)  // 设置作用范围
@Retention(RetentionPolicy.RUNTIME) // 设置生命周期
public @interface Table {
    String value();
}

主键Id.java

package demo2.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 主键注解
 *
 * @author Anna.
 * @date 2024/4/4 21:38
 */
@Target(ElementType.FIELD)  // 设置作用范围
@Retention(RetentionPolicy.RUNTIME) // 设置生命周期
public @interface Id {
}

字段注解Field.java

package demo2.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 字段
 *
 * @author Anna.
 * @date 2024/4/4 21:42
 */
@Target(ElementType.FIELD)  // 设置作用范围
@Retention(RetentionPolicy.RUNTIME) // 设置生命周期
public @interface Field {
    // 字段名称
    String columnName();
    // 类型
    String type();
    // 长度
    int length();
}

实体UserDo.java

package demo2;

import demo2.annotation.Field;
import demo2.annotation.Id;
import demo2.annotation.Table;

/**
 * |实体字段|表字段|备注|
 * |:---|:---|:---|
 * |id| int(10) | 主键 |
 * |name| varchar2(30) |-|
 *
 * @author Anna.
 * @date 2024/4/4 21:36
 */
@Table("USER_TABLE")
public class UserDo {

    @Id
    @Field(columnName = "id", type = "int", length = 10)
    private Integer id;

    @Field(columnName = "name", type = "varchar2", length = 30)
    private String name;

    public UserDo() {
    }

    public UserDo(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "UserDo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

测试案例AnnotationDemo.java

package demo2;

import demo2.annotation.Id;
import demo2.annotation.Table;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * 反射模拟处理注解新
 *
 * @author Anna.
 * @date 2024/4/4 21:35
 */
public class AnnotationDemo {
    public static void main(String[] args) throws Exception {
        // 反射获取UserDo
        String path = AnnotationDemo.class.getClassLoader().getResource("").getPath();
//        System.out.println(path);
        Class<?> clazz = Class.forName("demo2.UserDo");

        // 初始化实例
        UserDo userDo = (UserDo) clazz.getDeclaredConstructor().newInstance();

        // 定义SQL 字段
        StringBuffer sb = new StringBuffer();
        sb.append("CREATE TABLE ");

        // 获取表注解
        Table table = clazz.getAnnotation(Table.class);
        sb.append(table.value()).append(" {");
        // 获取所有属性
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 1; i <= fields.length; i++) {
            Field field = fields[i - 1];
            // 获取所有注解
            Annotation[] annotations = field.getAnnotations();
            String fieldStr = "";
            String idStr = "";
            for (Annotation a : annotations) {
                if (a instanceof demo2.annotation.Field) {
                    demo2.annotation.Field a1 = (demo2.annotation.Field) a;
                    fieldStr = a1.columnName() + " " + a1.type() + "(" + a1.length() + ")";
                } else if (a instanceof Id) {
                    idStr = " PRIMARY";
                }


            }
            sb.append(fieldStr).append(idStr);
            if (i < fields.length) {
                sb.append(",");
            }
        }
        sb.append("}");

        System.out.printf("输出SQL:%s%n = ", sb.toString());

    }
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

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

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

相关文章

如何根据黄金行情进行交易操作?

根据黄金行情进行交易操作是许多投资者关注的重要议题&#xff0c;黄金作为一种重要的避险资产和投资工具&#xff0c;其价格波动受多种因素影响&#xff0c;包括经济数据、地缘政治风险、货币政策等。为了有效地进行黄金交易操作&#xff0c;投资者需要综合考虑多方面因素&…

ST表---算法

相当于二分的思想&#xff0c;一直比较最值 ST的创建 现在创建成功&#xff0c;是应该如何查询的问题 ST表的查询 虽然这两区间有重叠&#xff0c;但是可以一个往前数&#xff0c;一个往后数&#xff0c;互不影响 时间复杂度 创建st表的复杂度为n*logn 使用时的复杂度为O(…

ROS 2边学边练(12)-- 创建一个工作空间

上一篇我们已经接触过工作空间的概念&#xff0c;并简单了解体验了一点构建包、测试包的流程&#xff0c;此篇会深入一点学习工作空间相关内容。 前言 一个工作空间是包含了ROS 2的功能包的目录&#xff08;文件夹&#xff09;&#xff0c;在使用ROS 2之前我们得激活一下目标工…

【信号与系统 - 1】周期信号的傅里叶级数展开

1 傅里叶级数展开的定义 已知&#xff1a;一个周期信号 f ( t ) f(t) f(t) 是一个直流分量&#xff08;幅度为 c 0 c_0 c0​&#xff09;加上一序列余弦信号分量&#xff08; w 0 w_0 w0​基波分量和与之成谐波关系的k次谐波分量 k w 0 kw_0 kw0​&#xff09;经过加权求和得到…

高并发场景下分布式事务处理方案探讨及代码实现

本文将深入探讨高并发场景下&#xff0c;分布式事务处理的方案。随着互联网的快速发展&#xff0c;对系统性能和稳定性的需求也日益增长&#xff0c;尤其在高并发场景下&#xff0c;分布式事务成为重中之重。在本文中&#xff0c;我将分享我对分布式事务的理论理解&#xff0c;…

多线程重点知识(个人整理笔记)

目录 1. java 多线程 1.1. 什么是进程?什么是线程? 1.1.1. 进程 1.1.2. 线程 1.1.3. 多线程 2. 并行和并发有什么区别&#xff1f; 3. 守护线程是什么&#xff1f; 4. 创建线程有哪几种方式&#xff1f; 4.1. 线程的常见成员方法 5. 线程安全问题 5.1. synchronize…

39.基于SpringBoot + Vue实现的前后端分离-无人智慧超市管理系统(项目 + 论文PPT)

项目介绍 随着互联网时代的发展&#xff0c;传统的线下管理技术已无法高效、便捷的管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;国家在环境要求不断提高的前提下&#xff0c;无人智慧超市管理系统建设也逐渐进入了信…

Spring Boot | Spring Boot的“数据访问“、Spring Boot“整合MyBatis“

目录: 一、Spring Boot”数据访问概述“二、Spring Boot”整合MyBatis”1. 基础环境搭建 (引入对应的“依赖启动器” 配置数据库的“相关参数”)① 数据准备 (导入Sql文件)② 创建项目&#xff0c;引入相应的启动器&#xff0c;编写数据库对应的“实体类”③额外添加pom.xml文…

尚硅谷50道Java面试题笔记 写的不全

b站链接&#xff1a;https://www.bilibili.com/video/BV1Bb411d7SL/?p4&vd_source714a8042f058b82c668750a0930ff9b0 1 mysql使用innodb引擎&#xff0c;请简述mysql索引的最左前缀如何优化orderby语句。 关键点&#xff1a; 如果排序字段不在索引列上&#xff0c;file…

Filter Listener Interceptor

文章目录 第一章 Filter1. 目标2. 内容讲解2.1 Filter的概念2.2 Filter的作用2.3 Filter的入门案例2.3.1 案例目标2.3.2 代码实现2.3.2.1 创建ServletDemo012.3.2.2 创建EncodingFilter 2.4 Filter的生命周期2.4.1 回顾Servlet生命周期2.4.1.1 Servlet的创建时机2.4.1.2 Servle…

趣学前端 | 类,我想好好继承它的知识点

背景 最近睡前习惯翻会书&#xff0c;重温了《JavaScript权威指南》。这本书&#xff0c;文字小&#xff0c;内容多。两年了&#xff0c;我才翻到第十章。因为书太厚&#xff0c;平时都充当电脑支架。 JavaScript 类 话说当年类、原型、继承&#xff0c;差点给我绕晕。 在J…

Excel、PowerQuery 和 ChatGPT 终极手册(下)

原文&#xff1a;Ultimate ChatGPT Handbook for Enterprises 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 使用 SUMIFS、SUMPRODUCT、AGGREGATE 和 MAX 函数查找数值数据 其中之一鲜为人知的事实是&#xff0c;当查找单个数值时&#xff0c;匹配和三角函数可能比查…

软考--软件设计师(软件工程总结1)

目录 1.定义 2.软件生存周期 3.软件过程&#xff08;即软件开发中遵循的一系列可预测的步骤&#xff09; ​编辑4.软件开发模型 5.需求分析&#xff08;软件需求分析&#xff0c;系统需求分析或需求分析工程&#xff09; 6. 需求工程 7.系统设计 8.系统测试 1.定义 软件…

Android Studio学习9——使用Logcat打印日志

在Android开发中&#xff0c;Logcat是一个工具&#xff0c;它允许开发者查看设备或模拟器的日志信息。开发者可以使用Log类来打印日志信息&#xff0c;这对于调试和错误排查非常有帮助。 v 或 verbose: 最低等级&#xff0c;显示所有消息。d 或 debug: 用于调试消息。i 或 info…

在集群中使用deepspeed如果端口被占用可以使用deepspeed参数更改

在集群中使用deepspeed如果端口被占用可以使用deepspeed参数更改 这一次G老师不好使了 在集群中使用deepspeed默认的端口号29500被占用&#xff0c;显示更改居然不起作用 G老师给的方法也不好使 #!/bin/bash MASTER_ADDRlocalhost MASTER_PORT29501 # 选择一个未被占用的端…

Qt | 发布程序(以 minGW 编译器为例)

1、注意:修改 pro 文件后,最好执行“构建”>“重新构建项目”,否则 pro 文件的更改将不会反应到程序上。 2、发布程序的目的:就是让编译后生成的可执行文件(如 exe 文件),能在其他计算机上运行。 一、编译后生成的各种文件简介 Qt Creator 构建项目后产生的文件及目录…

SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型…

鸿蒙原OS开发实例:【ArkTS类库单次I/O任务开发】

Promise和async/await提供异步并发能力&#xff0c;适用于单次I/O任务的场景开发&#xff0c;本文以使用异步进行单次文件写入为例来提供指导。 实现单次I/O任务逻辑。 import fs from ohos.file.fs; import common from ohos.app.ability.common;async function write(data:…

文心一言指令词宝典之生活篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

前端三剑客 —— CSS (第一节)

目录 CSS 什么是CSS CSS的几种写法&#xff1a; 行内样式 内嵌样式 外链样式 import 加载顺序 CSS选择器*** 基本选择器 ID选择器 标签选择器 类选择器 通用选择器 包含选择器 上节内容中提到了 前端三剑客 —— HTML 超文本标记语言&#xff0c;这节内容 跟大家…