注解与自定义注解

1 注解

注解很厉害,它可以增强我们的java代码,同时利用反射技术可以扩充实现很多功能。它们被广泛应用于三大框架底层。
传统我们通过xml文本文件声明方式(如下图,但是XML比较繁琐且不易检查),而现在最主流的开发都是基于注解方式,代码量少,框架可以根据注解去自动生成很多代码,从而减少代码量,程序更易读。例如最火爆的SpringBoot就完全基于注解技术实现。
xml示例
注解设计非常精巧,初学时觉得很另类甚至多余,甚至垃圾。有了java代码干嘛还要有@注解呢?但熟练之后你会赞叹,它竟然可以超越java代码的功能,让java代码瞬间变得强大。大家慢慢体会吧。

2 注解的分类

注解一共分为3大类,我们先来认识一下:

  • JDK自带注解
  • 元注解
  • 自定义注解

2.1 JDK注解

JDK注解的注解,就5个:

@Override :用来标识重写方法

@Deprecated标记就表明这个方法已经过时了,但我就要用,别提示我过期
@SuppressWarnings(“deprecation”) 忽略警告
@SafeVarargs jdk1.7出现,堆污染,不常用
@FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用

2.2 元注解

用来描述注解的注解,就5个:

@Target 注解用在哪里:类上、方法上、属性上等等
@Retention 注解的生命周期:源文件中、字节码文件中、运行中

@Inherited 允许子注解继承
@Documented 生成javadoc时会包含注解,不常用
@Repeatable注解为可重复类型注解,可以在同一个地方多次使用,不常用

2.2.1 @Target ElementType…

描述注解存在的位置:

ElementType.TYPE 应用于类的元素
ElementType.METHOD 应用于方法级
ElementType.FIELD 应用于字段或属性(成员变量)
ElementType.ANNOTATION_TYPE 应用于注释类型
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.PACKAGE 应用于包声明
ElementType.PARAMETER 应用于方法的参数

2.2.2 @Retention RetentionPolicy…

该注解定义了自定义注解被保留的时间长短,比如某些注解仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中; 编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取。
编译运行顺序为何要分字节码文件中有还是没有呢?如果没有时,反射技术就拿不到,从而就无法去识别处理。它的值一共3种:

SOURCE 在源文件中有效(即源文件保留)
CLASS 在class文件中有效(即class保留)
RUNTIME 在运行时有效(即运行时保留)

3 自定义注解

注意:注解的语法写法和常规java的语法写法不同

创建包: cn.tedu. annotation
创建类: TestAnnotation.java

package cn.tedu.annotation;

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

/*本类用于测试自定义注解/
public class TestAnnotation { }

//1.2通过@Target注解表示此自定义注解可以使用的位置
/**2.注意@Target注解使用时需要导包

  • 通过ElementType.静态常量值来指定此自定义注解可以标记的元素
  • 如果有多个值,可以使用"{ , } "的格式来写:@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
  • */
    @Target(ElementType.METHOD)//表示此注解可以用来标记方法
    //1.3通过@Retention注解表示自定义注解的声明周期
    /**3.注意@Retention使用时需要导包
  • 通过RetentionPolicy.静态常量值来指定此自定义注解的生命周期
  • 也就是指自定义注解可以存在在哪个文件中:源文件/字节码文件/运行时,只能3选1,不能写多个,因为源码:RetentionPolicy value();
  • */
    @Retention(RetentionPolicy.SOURCE)
    //首先注意:自定义注解的语法与java不同,不要套用java的语法
    //1.1定义自定义注解,注解名是Test
    /*1.注解定义需要使用"@interface 注解名" 的方式来定义/
    @interface Test{
    /**5.自定义注解还可以添加功能–给注解添加属性
    • 注意int age();不是方法的定义,而是给自定义注解中定义age属性的语法
      *如果为了使用注解时方便,还可以给age属性指定默认值,这样就可以直接使用,格式:“int age() default 0;”
    • */
      //int age();
      int age() default 0;
      /**6.注解中还可以添加功能–可以定义特殊属性value
    • 特殊属性的定义方式与别的属性相同,主要是使用方式不同
    • 使用此注解给属性赋值的时候可以不用写成"@Test(value = “apple”)",格式可以简化成"@Test(“apple”)",直接写值
    • 但是在自定义注解类中的赋予默认值不能简写,如果自定义了默认值,使用时可以不用赋值直接使用属性的默认值
    • */
      String value() default “lemon”;
      }
      /*4.使用注解时,只要在指定的自定义注解名字前加上@即可使用此注解/
      //2.1自定义一个类用来测试自定义注解
      //@Test
      class TestAnno{
      /**测试1:给TestAnno类/name属性/eat()都添加了@Test注解,只有方法上不报错
    • 结论: 自定义注解能够加在什么位置,取决于@Target的值
    • 测试2:修改@Target的值@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE}),3个@Test都不再报错
    • 结论:注解@Test可以有多个位置,多个值,可以使用"{ , } "的格式,@Target中维护的是ElementType[]
    • */
      //@Test
      String name;
      /**测试3:添加了age属性以后,@Test注解报错
    • 结论:当注解没有定义属性时,可以直接使用,如果有属性了,就需要给属性赋值
    • 测试4:给@Test注解的age属性赋值以后,就不报错了
    • 结论:给属性赋值时的格式"@Test(age = 10)",注意,不能直接写10这种错误格式
      *测试5:给age属性赋予默认值后,还可以不加属性直接使用@Test注解,此时使用的就是age属性的默认值0
    • /
      /**测试6:给特殊属性value赋值时可以简写,相当于value=“lemon”
      /
      //@Test(“lemon”)
      @Test/*测试7:因为已有默认值,所以不用给特殊属性value赋值,直接使用@Test/
      public void eat() {
      System.out.println(“干饭啦!”);
      }
      }

    恭喜你,又闯过一关,后续框架部分我们会频繁使用注解,祝你有个好的开端

    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值