【Java高级】一篇文章带你学会什么是注解

news2024/9/20 19:33:12

目录

注解概述

| Java内置的三个注解

@Deprecated

@Override

@SuppressWarnings

| 元注解

@Target

@Retention(注解生命周期)

@Documented

@Inherited

@Repeatable(JDK1.8)

| 自定义注解

自定义注解的概述

自定义注解的步骤

自定义注解应用示例


本文参考了部分资料,在此声明,侵删。

参考资料1

参考资料2

参考资料3

注解概述

什么是注解?

  • 注解也属于一种类型

  • 类上、属性上、方法上、变量上、注解类型上,均可以出现注解!

  • Java注解用于为Java代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。

  • Java注解通常用于以下目的:

    • 编译器指令:Java有3个内置的注解,你可以用它来发出指令到Java编译器。

    • 编译时指令:当创建建软件项目时,Java注释可以在编译时使用。构建过程包括生成的源代码,编译源文件,生成XML文件(例如部署描述符),包装编译代码和文件到一个JAR文件等。构建软件通常是通过像Apache Ant组织的Apache Maven的自动构建工具完成。构建工具可以扫描你的Java代码指定的注解并生成源代码或基于这些注解其他文件

    • 运行时指令:通常情况下,Java注解中不存在于编译后的Java代码。这是可能的,但是,定义自己的注解是在运行时可用。这些注解然后可以通过Java反射访问,并用于发出指令到程序,或者一些第三方API

注解的作用

  • 生成文档的注解,如@author,@param。

  • 跟踪代码依赖性,实现替代配置文件功能,如spring mvc的注解。

  • 编译时进行格式检查,如@override。

  • 编译时进行代码生成补全,如lombok插件的@Data。

注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。

注解有许多用处,主要如下:

  • 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息

  • 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。

  • 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取 值得注意的是,注解不是代码本身的一部分。


| Java内置的三个注解

@Deprecated

  • 用来注解过时的东西,如类或方法的注解; 如果使用的东西过时,编译器会通知应该使用的另一种方式。或IDE工具,像Eclipse,它也给显示出可视化通知

package com.yiibai.tutorial.ann.builtin;

import java.util.Date;

public class DeprecatedMethodDemo {

   /**
    * @deprecated replaced by {@link #todo(String,Date)}
    */
   @Deprecated
   public void todoJob(String jobName) {
       System.out.println("Todo " + jobName);
   }
    
   public void todo(String jobName, Date atTime) {
       System.out.println("Todo " + jobName + " at " + atTime);
   }
    
   public void todoNothing() {
       System.out.println("Todo Nothing");
   }
    
   public static void main(String[] args) {

       DeprecatedMethodDemo obj = new DeprecatedMethodDemo();
       obj.todoJob("Java coding");
       obj.todoNothing();
   }
}

 


@Override

  • @Override注解来覆盖超类方法在方法使用。如果这个方法不超匹配的方法,编译器就会提示一个错误。

  • @Override注解不是必需的。如坚持使用它,也是个好主意。万一有人改变超类中的重写方法名称,子类的方法将不再覆盖它。可能不太好找到问题。

  • @Override注解,用于更好地查找在子类中的方法没有完全重写超类的方法

 


@SuppressWarnings

@SuppressWarnings注解使编译器抑制对某个方法的警告。例如,如果一个方法调用的方法已过时,或使一个不安全的类型转换,编译器可能会产生一个警告。可以通过包含使用@SuppressWarnings注解代码的方法标注抑制这些警告s

示例1

package com.yiibai.tutorial.ann.builtin;
import java.util.Date;
public class SuppressWarningsDemo {

   @SuppressWarnings("deprecation","unused")
   public Date getSomeDate() {
       Date date = new Date(2014, 9, 25);
       return date;
   }
}

 

示例2

package com.yiibai.tutorial.ann.builtin;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class SuppressWarningsDemo2 {

  public List<?> getDatas() {
      List<String> list = new ArrayList<String>();
      list.add("One");
      return list;
  }

  @SuppressWarnings({ "deprecation", "unused", "unchecked" })
  public void processDatas() {  
      // You use deprecated Constructor
      // Variable 'date' was created, but not used      
      Date date = new Date(2014, 9, 25);

      // Cast unsafe.
      // Variable 'datas' is created, but not used in the code.      
      List<String> datas= (List<String>) this.getDatas();        
  }
}

 


| 元注解

  • 元注解可以理解为 “用于修饰注解的注解”,指定注解可以修饰的位置

@Target

  • 用于指定被修饰的注解可以放置的位置(如@Override注解被 @Target(ElementType.METHOD) 修饰,所以只能作用于方法)

@Target(value={CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACAKGE,MODULE,PARAMATER,TYPE})
@其他注解

//也可以写成下面这种语法
@Target({FIELD , METHOD})

可以写的值有

    ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
    ElementType.CONSTRUCTOR 可以给构造方法进行注解
    ElementType.FIELD 可以给属性进行注解
    ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
    ElementType.METHOD 可以给方法进行注解
    ElementType.PACKAGE 可以给一个包进行注解
    ElementType.PARAMETER 可以给一个方法内的参数进行注解
    ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Retention(注解生命周期)

  • 用于被修饰的注解会被保存在哪儿、能否被反射到

@Retention(RetentionPolicy . SOURCE) //只被保存在java源文件(即源文件保留)
@Retention(RetentionPolicy . CLASS) //被保存在class文件中(即class保留)
@Retention(RetentionPolicy . RUNTIME) //被保存在class文件中,并能够被反射机制所读取 (即运行时保留)
  • RetentionPolicy.SOURCE : 仅存在于源代码中,编译阶段会被丢弃,不会包含于class字节码文件中。@Override, @SuppressWarnings都属于这类注解。

  • RetentionPolicy.CLASS : 默认策略,在class字节码文件中存在,在类加载的时被丢弃,运行时无法获取到。

  • RetentionPolicy.RUNTIME : 始终不会丢弃,可以使用反射获得该注解的信息。自定义的注解最常用的使用方式。


@Documented

能够将注解中的元素包含到 Javadoc 中去。


@Inherited

Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。


@Repeatable(JDK1.8)

注解的值可以同时取多个。举个例子,一个人他既是程序员又是产品经理,同时他还是个画家。

@interface Persons {
    Person[]  value();
}
@Repeatable(Persons.class)
@interface Person{
    String role default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}



| 自定义注解

自定义注解的概述

  • 注:注解只是一种标记,如果不解析,它是不会实现任何功能的

  • 自定义注解本质上是继承自Annotation的类

  • 自定义注解的作用:自定义注解就是在注解内添加一系列的属性,然后通过元注解限定注解的位置,

    接着在代码中通过反射(只有被元注解 @Retention(RetentionPolicy.RUNTIME) 修饰的注解才能被反射到),获取到注解内的值,完成一些业务逻辑代码


自定义注解的步骤

定义自定义注解使用 @interface 关键字

@interface是声明一个注释的关键字,而这个注解非常相似于接口。注解可有或没有元素。注释元素的特点:

  • 元素可以有默认值;

  • 没有函数体;

  • 没有函数参数;

  • 返回的声明必须在一个特定的类型:

    • 基本类型 (boolean, int, float,…)

    • 枚举

    • 注解

    • 类(如:String.class)

使用元注解来限定自定义注解

  • 使用元注解@Target来标记该注解的作用范围(空间范围,在哪些地方可以使用)

  • 使用元注解@Retention来标记该注解的作用时间范围(时间范围,在什么时候起作用)

  • 使用元注解@Inherited来标记该注解是否可以由子注解来继承

  • 使用元注解@Documented来标记该注解是否需要自动生成文档

  • 使用@interface关键词来定义注解

创建自定义注解代码示例

//Step1.根据语法搭建语法框架、根据需要添加元注解
//Step2.给注解添加属性、【赋默认值】

@元注解
public @interface 自定义注解名MyAnnotation{

	//元素String name,默认值""
	String name() [default ""];
    int age();

}

使用自定义代码(给属性赋值)

//给自定义注解的属性赋值:常规方法
@MyAnnotation(age = 8 , name = "Klee");

//给自定义注解的属性赋值:只有一个属性 且 属性名为value(此时可以省略value这个名字)
//假设AnnotationValue中只有一个  int value(); 属性
@AnnotationValue(100);
//假如除了value属性还有别的属性,则只能按照常规方法老实赋值啦

//给自定义注解的属性赋值:属性有数组(假设名字为array)
@AnnotationArray(people = {"Klee","Sagiri"});   //数组有多个元素
@AnnotationArray(people = "Klee");   //数组只有一个元素

自定义注解应用示例

  • 下边定义一个注解@Range用来校验对象的字段长度是否符合自定义约束

  • 再次强调:自定义注解通常结合反射 + AOP来使用,比较高深,尽可能看懂。

注解类 Range.class

/**
 * @author sunhongmin
 * @Date 2020-10-21
 * @Describe 字段长度约束,默认0-255
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)  //只有被@Rention修饰的注解才能被反射到!
public @interface Range {
    int min() default 0;
    int max() default 255;
}

测试类 RangeTestDemo.class

package com.annotation;

import java.lang.reflect.Field;

class User {
    /**
     * 最大长度为10
     */
    @Range(max = 10)
    public String name;

    /**
     * 使用默认值255
     */
    @Range
    public String address;

    public User() {
    }

    public User(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

public class RangeTestDemo {

    public static void checkRange(User user) throws IllegalAccessException {
        Field[] declaredFields = user.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            // 如果标注了Range注解
            if (field.isAnnotationPresent(Range.class)) {
                // 获取注解
                Range range = field.getAnnotation(Range.class);
                // 获取field值
                Object value = field.get(user);
                if (value instanceof String) {
                    String str = (String) value;
                    if (str.length() < range.min() || str.length() > range.max()) {
                        throw new IllegalArgumentException("Invalid field:{" + field.getName() + "},value:{" + str + "},Limit range [" + range.min() + "," + range.max() + "]");
                    }

                }

            }
        }
    }

    public static void main(String[] args) throws IllegalAccessException {
        User user = new User("张大彪啊啊啊啊啊啊啊asdasdasdasda", "地址在哪呢在哪在哪在哪在哪在哪在哪在哪在哪在哪在哪在哪在哪");
        RangeTestDemo.checkRange(user);
    }
}

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

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

相关文章

货币政策传导与货币政策调控-中国视角下的宏观经济

货币政策传导与货币政策调控-潘登同学的宏观经济学笔记 文章目录货币政策传导与货币政策调控-潘登同学的宏观经济学笔记货币传导路径货币是银行的负债——货币的“形而下”定义贷款创造存款货币乘数货币就是记忆&#xff08;money is memory&#xff09;——货币的“形而上”定…

libevent库

libevent介绍 1 事件驱动, 高性能, 轻量级, 专注于网络 2 源代码精炼, 易读 3 跨平台 4 支持多种I/O多路复用技术, 如epoll select poll等 5 支持I/O和信号等事件 libevent的核心实现: 在linux上, 其实质就是epoll反应堆. libevent是事件驱动, epoll反应堆也是事件驱动, 当要…

硬件基础 -- D/A数字模拟信号

D/A 需要数位模拟开关 如果开关打卡&#xff0c;则此位电压参与运算 如果开关关闭&#xff0c;则此位电压0V参与运算 转换过程中需要将数字数字量锁存 转换过程 模拟量转数字量需要比较器 数字量转模拟量需要运放 #mermaid-svg-wJVhc3DQ619gtYuZ {font-family:"trebuchet …

【计算机毕业设计】6.超市仓库管理系统+vue

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 基于B/S的超市进销存管理系统的设计与实现 摘 要&#xff1a;开发本超市进销存管理系统的主要目标是方便企业对商品、客户和员工信息的实时掌控&#xff0c;提高企业的工作效率。本系统是采用java开发的一个基于B/S…

渗透测试——基于SQL注入拿到webshell

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

spring整合struts2

因为最近工作的需要不得不学习struts2&#xff0c;整理了一下spring整合struts2的过程 需要详细了解struts2的朋友可以自行百度&#xff0c;这里只是简单的讲述如何使用 我是用的是idea进行项目构建的&#xff0c;eclipse的话可以自己百度一下 struts的官网&#xff1a;https:…

PTA题目 阶梯电价

为了提倡居民节约用电&#xff0c;某省电力公司执行“阶梯电价”&#xff0c;安装一户一表的居民用户电价分为两个“阶梯”&#xff1a;月用电量50千瓦时&#xff08;含50千瓦时&#xff09;以内的&#xff0c;电价为0.53元/千瓦时&#xff1b;超过50千瓦时的&#xff0c;超出部…

前缀和【一维前缀和与二维前缀和】

全文目录&#x1f600; 一维前缀和&#x1f914; 构建一维前缀和数组&#x1f635;‍&#x1f4ab; 子序列的和&#x1f600; 二维前缀和&#x1f914; 构建二维前缀和数组&#x1f635;‍&#x1f4ab; 子矩阵的和&#x1f600; 一维前缀和 一维前缀和很简单&#xff0c;就是…

[附源码]java毕业设计铁路法院数字档案管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]java毕业设计网上花店系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

同步时序逻辑电路

分类 按逻辑功能不同分为&#xff1a;RS触发器、D触发器、JK触发器、T触发器。按触发方式不同分为&#xff1a;电平触发器、边沿触发器和脉冲触发器。按电路结构不同分为&#xff1a;基本RS触发器和钟控触发器。按存储数据原理不同分为&#xff1a;静态触发器和动态触发器。按…

【从零开始学微服务】03.软件架构的演化过程

大家好&#xff0c;欢迎来到万猫学社&#xff0c;跟我一起学&#xff0c;你也能成为微服务专家。 目前大部分的企业系统和互联网应用都是采用Web的形式提供服务能力&#xff0c;根据系统的组织方式和部署结构&#xff0c;我们通常把软件架构的演化过程分为以下几个阶段&#xf…

微信小程序实战,基于vue2实现瀑布流

1、什么是瀑布流呢&#xff1f; 瀑布流&#xff0c;又称瀑布流式布局。是比较流行的一种网站页面布局&#xff0c;视觉表现为参差不齐的多栏布局&#xff0c;随着页面滚动条向下滚动&#xff0c;这种布局还会不断加载数据块并附加至当前尾部。 瀑布流对于图片的展现&#xff0c…

HTML+CSS+JS大作业:生态环境网站设计——环境保护主题 大学生环保主题网页制

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 环境保护 | 保护地球 | 校园环保 | 垃圾分类 | 绿色家园 | 等网站的设计与制作HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样…

【计算机编程基础】

计算机编程基础1 本节目标2 编程语言2.1 编程2.2 计算机语言2.3 编程语言2.4 翻译器2.5 编程语言和标记语言区别3 计算机基础3.1 计算机组成3.2 数据存储3.3 数据存储单位3.4 程序运行1 本节目标 说出什么是编程语言区分编程语言和标记语言的不同说出常见的数据存储单位及其换…

Maven入门学习——使用IDEA创建Maven文件的两种方式(内含配置setting文件)

使用IDEA创建Maven文件的两种方式一、前言二、前期准备&#xff08;配置setting文件&#xff09;1.修改文件放置位置2.改用阿里云镜像3.修改默认JDK版本三、构建Maven项目1.新建空项目2.设置项目中Maven版本3.新建模块4.配置模块5.测试四、使用插件创建Maven项目1.新建Maven项目…

Python字典制作“编码本”“密码本”,“试炼”加、解密文本操作

【点击此处跳转笔记正文】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… My CSDN主页、My HOT博、My Python 学习个人备忘录好文力荐、 老齐教室 自学并不是什么神秘的…

【k8s】2、二进制安装k8s

文章目录一、环境准备二、操作系统的初始化三、部署Etcd集群1、 准备cfssl证书生成工具2、生成etcd证书3、部署Etcd集群四、安装docker(所有node节点)五、部署master组件1、 准备证书2、 准备二进制文件、token3、 启动kube-apiserver服务4、启动scheduler服务5、启动controlle…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.15 ES 文档操作

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.15 ES 文档操作4.15.1 文档操作4.15.2 小结4 数据…

最新最全面的Spring详解(四)——面向切面编程

前言 本文为 【Spring】面向切面编程 相关知识&#xff0c;下边将对AOP概述&#xff08;包含什么是AOP、AOP相关术语、Spring AOP通知类型&#xff09;&#xff0c;Spring AOP能力和目标&#xff0c;AOP代理&#xff0c;AspectJ风格的支持&#xff08;包含对于 AspectJ的支持、…