面试官:什么是 Java 注解?(上)

简介: 哈喽,我是狗哥。随着开发经验的累积,我越发觉得基础真的非常重要。比如:大部分框架 (如 Spring) 都使用了注解简化代码并提高编码的效率,掌握注解是一名 JAVA 程序员必备的技能。但我发现很多工作 2、3 年的同学居然还没写过自定义注解,问起注解的原理也是一脸懵。我是很震惊的,你们咋理解代码的?基于此,今天我们就来一起学习下注解。

01 什么是注解?


Java 注解(Annotation),相信大家没用过也见过。个人理解,注解就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,从而做相对应的处理


注解跟注释很像,区别是注释是给人看的(想想自己遇到那些半句注释没有的业务代码,还是不是很难受?);而注解是给程序看的,它可以被编译器读取


1.1 注解的作用


注解大多时候与反射或者 AOP 切面结合使用,它的作用有很多,比如标记和检查,最重要的一点就是简化代码,降低耦合性,提高执行效率。比如我司就是通过自定义注解 + AOP 切面结合,解决了写接口重复提交的问题。


简单描述下我司防止重复提交注解的逻辑:请求写接口提交参数 —— 参数拼接字符串生成 MD5 编码 —— 以 MD5 编码加用户信息拼接成 key,set Redis 分布式锁,能获取到就顺利提交(分布式锁默认 3 秒过期),不能获取就是重复提交了,报错


640.png


如果每加一个写接口,就要写一次以上逻辑的话,那程序员会疯的。所以,有大佬就使用注解 + AOP 切面的方式解决了这个问题。只要在写接口 Controller 方法上加这个注解即可解决,也方便维护


1.2 注解的语法


以我司防止重复提交的自定义注解,介绍下注解的语法。它的定义如下:


// 声明 NoRepeatSubmit 注解
@Target(ElementType.METHOD) // 元注解
@Retention(RetentionPolicy.RUNTIME) // 元注解
public @interface NoRepeatSubmit {
 /**
     * 锁定时间,默认单位(秒)
     */
 long lockTime() default 3L;
}


Java 注解使用 @interface 修饰,我司的 NoRepeatSubmit 注解也不例外。此外,还使用两个元注解。其中 @Target 注解传入 ElementType.METHOD 参数来标明 @NoRepeatSubmit 只能用于方法上@Retention(RetentionPolicy.RUNTIME) 则用来表示该注解生存期是运行时,从代码上看注解的定义很像接口的定义,在编译后也会生成 NoRepeatSubmit.class 文件。


1.3 注解的元素


定义在注解内部的变量,称之为元素。注解可以有元素,也可以没有元素。像 @Override 就是无元素的注解,@SuppressWarnings 就属于有元素的注解。


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


@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}


带元素的自定义注解:


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoRepeatSubmit {
    /**
     * 锁定时间,默认单位(秒)
     */
    long lockTime() default 2L;
}


1.3.1 注解元素的格式


注解的元素格式如下:


// 基本格式
数据类型 元素名称();
// 带默认值
数据类型 元素名称() default 默认值;


1.3.2 注解元素的数据类型


注解元素支持如下数据类型:


所有基本类型(int,float,boolean,byte,double,char,long,short)
String
Class
enum
Annotation
上述类型的数组


声明注解元素时可以使用基本类型但不允许使用任何包装类型,同时注解也可以作为元素的类型,也就是嵌套注解


1.3.3 编译器对元素默认值的限制


遵循规则:


  • 元素要么具有默认值,要么在使用注解时提供元素的值。
  • 对于非基本类型的元素,无论是在源代码中声明,还是在注解接口中定义默认值,都不能以 null 作为值。


1.4 注解的使用


注解是以 @注释名 的格式在代码中使用,比如:以下常见的用法。


public class TestController {
    // NoRepeatSubmit 注解修饰 save 方法,防止重复提交
    @NoRepeatSubmit
    public static void save(Object o){
        // 保存逻辑
    }
    // 一个方法上可以有多个不同的注解
    @Deprecated
    @SuppressWarnings("uncheck")
    public static void getDate(){
    }
}


在 save 方法上使用 @NoRepeatSubmit (我司自定义注解),加上之后,编译期会自动识别该注解并执行注解处理器的方法,防止重复提交;


而对于 @Deprecated@SuppressWarnings (“uncheck”),则是 Java 的内置注解,前者意味着该方法是过时的,后者则是忽略指定的异常检查。

相关文章
|
1天前
|
Java
Java自定义注解:优雅的代码标记
Java自定义注解:优雅的代码标记
9 1
|
1天前
|
Java 开发者
Java文档注解中@link与@see的使用详解
Java文档注解中@link与@see的使用详解
4 0
|
1天前
|
负载均衡 NoSQL Dubbo
java分布式面试快问快答
java分布式面试快问快答
9 0
|
1天前
|
XML Java 数据库连接
面试必备!Java核心技术100+面试题
面试必备!Java核心技术100+面试题
|
1天前
|
Java API 数据处理
Java Bean参数验证:深入探索javax.validation.constraints注解
Java Bean参数验证:深入探索javax.validation.constraints注解
6 0
|
1天前
|
算法 Java 调度
《面试专题-----经典高频面试题收集四》解锁 Java 面试的关键:深度解析并发编程进阶篇高频经典面试题(第四篇)
《面试专题-----经典高频面试题收集四》解锁 Java 面试的关键:深度解析并发编程进阶篇高频经典面试题(第四篇)
6 0
|
1天前
|
安全 Java 中间件
《面试专题-----经典高频面试题收集一》解锁 Java 面试的关键:深度解析常见高频经典面试题(第一篇)
《面试专题-----经典高频面试题收集一》解锁 Java 面试的关键:深度解析常见高频经典面试题(第一篇)
8 0
|
1天前
|
安全 Java API
《面试专题-----经典高频面试题收集三》解锁 Java 面试的关键:深度解析并发编程基础篇高频经典面试题(第三篇)
《面试专题-----经典高频面试题收集三》解锁 Java 面试的关键:深度解析并发编程基础篇高频经典面试题(第三篇)
5 0
|
3天前
|
Java 数据安全/隐私保护 Spring
Java中的编译时与运行时注解
Java中的编译时与运行时注解
|
3天前
|
Java
Java中的面试常见问题解析
Java中的面试常见问题解析