Java中的注解详讲

1 什么是注解

  • jdk5提供了一个新的应用 Annotation, 注解, 注释

  • 与之前所学的注释的区别

    • 之前的注释:是给程序员看 ,让程序员知道程序(代码)有什么用,实现了什么功能

    • 今天的注解:是给编辑器或jvm看的。在编译和运行时提供一些信息,按照信息完成后续的工作

      我们在开发中经常使用注解作为配置信息的载体。类似于xml配置文件的作用。

2 注解的分类

  1. 普通注解,在编程中经常用来作为配置的注解,包括jdk自带的注解和自定义注解

    • @Override 告诉编译,当前方法按照重写的规则检查。

    • @Deprecated 告诉编译器,当前说明的内容是过时的,不建议使用的。但可以继续使用

    • @SuppressWarnings 告诉编译,当前说明的内容相关的警告可以忽略

  2. 元注解,用来说明注解的注解 。 未来还有一个概念:元数据

    用户信息:dmy , 18 , 男, 30000

    元数据:姓名,字符串类型,最长10个字符 , 性别,年龄,工资

    元注解有4个

    • @Target 用来说明当前注解都可以作用在哪些内容上

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface SuppressWarnings {}

   2.@Retention 用来说明当前注解存活范围,有3个范围, 只能3选1

RetentionPolicy.SOURCE;  //表示在原码到字节码编译过程中有效。编译后消失
RetentionPolicy.CLASS;	//表示在类加载过程中有效,加载完消失。
RetentionPolicy.RUNTIME;//表示在jvm运行时都有效。
  • 3.@Documented 用来说明当前注解在生成api文档时,会一同出现在文档中。

  • 4.@Inherited 用来说明当前注解在类继承的过程中,可以一同被继承。

3 注解语法结构

  • 注解是一个特殊的类,使用@interface 定义注解

public @interface A{}

 使用元注解,在普通注解头上来说明注解特性。至少要使用@Retention 和 @Target

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface A {}

 注解里只能写一种内容 (可以称为属性 也 可以称为方法)

public @interface A{
    String i();
}
  • 该内容类型只能是以下几种

    • String

    • 8种基本类型

    • Class

    • 其他注解类型 , 当注解作为类型时,不需要加前面的@

    • 枚举类型

    • 上述所有类型的数组类型

  • 可以使用default关键字,为注解中的属性设置默认值

 

public @interface A{
    String name() default "dmy"  ;
    String[] names() default {"dmy","zs","ls"};
}

4 注解的使用

  • 使用注解,提供配置信息

    • 根据Target元注解的指定,可以在对应的类的内容上使用注解

    • 如果注解中有属性,可以在使用注解时,类似于传参的方式为属性赋值

    • 属性赋值时,需要指定属性名和其对应的属性值

    • 如果属性是数组类型,多个属性值要使用{}包含

@A(name="zhangsan",names={"zs","ls","ww"})
class B{}

 

特殊情况说明

  • 如果注解不需要传递属性值 (没有属性,都有默认值),后面的括号可有可无

@A()
@A
class B{}

 如果注解中只有一个属性需要赋值,且这个属性名叫value。赋值时可以只写值,不写名

@interface A{
    String value();
}

 如果注解属性是数组类型,且传参赋值时只赋予一个值,可以省略{}

@A(name="zs",names={"dmy"})
@A(name="zs",names="dmy")
class B{}

 

使用注解,获得配置信息

  • 注解在使用时,也是类的一部分

  • 可以通过反射获得注解,进而获得注解中配置的信息

  • 反射中常用的对象(Class,Field , Method , Constructor)都提供了获得注解对象的方法

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface A {
    String value() ;
}

 

public class Test3 {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<B> c = B.class;

        A a = c.getAnnotation(A.class);
        System.out.println(a.value());

        Field i = c.getDeclaredField("i");
        Annotation[] annotations = i.getAnnotations();
        for(Annotation annotation : annotations){
            Method value = annotation.getClass().getMethod("value");
            Object v = value.invoke(annotation);
            System.out.println(v);
        }
    }
}


@A("dmy")
class B{
    @A(value="dongmingyu",i="zs")
    @SuppressWarnings("all")
    int i ;
}

补充:所有的注解,都默认继承Annotation父注解类型

5 特殊情况的注解使用

  • 注解的重复使用

    • 默认情况下,无法使用两个相同的注解,修饰同一个类信息

    • 以前解决方案是定义一个新注解,新注解中有一个数组属性,可以包含多个所需要注解

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AS {
    A[] value();
}
@AS({
    @A("zs") ,
    @A("ls") , 
    @A("ww")
})
class B{}

 

  • 现在可以在注解上使用另一个注解@Repeatable(AS.class) 指定当前注解重复出现的时候,会自动的将重复的注解组成指定的那个@AS注解

    @AS还需要正常定义

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(AS.class)
public @interface A {}

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AS {
    A[] value();
}

 

@A("zs")
@A("ls")
@A("ww")
class C{}

函数式接口

  • 这是lambda表达式相关的一个概念

  • lambda表达式针对的必须是接口,而且只能有一个抽象方法。这样的接口就称为函数式接口

  • 函数式接口,可以使用@FunctionalInterface声明。 在编译就会按照函数式接口的特点进行检测

 

@FunctionalInterface
interface A{
    void t1();
}
  • 使用注解声明,必须是函数式接口

  • 函数式接口,不一定使用注解声明

 

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值