现代的Java编程过程中,会经常需要使用到注解,各种流行框架,比如在使用spring进行应用构建的过程中会使用到非常多的spring注解。

本文简要谈一谈Java注解以及如何去定义自己的注解在程序中进行使用的。




java中value什么意思 value在java中的意思_java注解


注解简介

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

主要作用

提供信息给编译器: 编译器可以利用注解来探测错误和警告信息编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

定义

注解和类、接口等是一个层次的东西,它的声明是用@interface标识的,跟接口很像,如下所示:

public @interface Newday {}

元注解-注解的注解

jdk1.8给我们提供了如下注解:

1.@Target2.@Retention3.@Documented4.@Inherited5.@Native6.@Repeatable

上面这些类型都在jdk提供的java.lang.annotation包中。简要介绍如下。

@Documented

使用这个注解,可以让注解中的元素包含到javadoc或者类似的工具上去。

// Indicates that annotations with a type are to be documented by javadoc and similar tools by default.

@Target

限定运用场景,可以同时限定多个,比如说新定义一个注解,限定在类型和方法注解。

// Indicates the contexts in which an annotation type is applicable.

主要有以下几种:

// 限定给类型注解,比如说类、接口、枚举等    TYPE,    // 限定给属性注解    FIELD,    // 限定给方法注解    METHOD,    // 限定给参数注解    PARAMETER,    // 限定给构造函数注解    CONSTRUCTOR,    // 限定给局部变量注解    LOCAL_VARIABLE,    // 限定在注解上注解    ANNOTATION_TYPE,    // 限定在包上使用注解    PACKAGE

@Retention

保留期,即注解可以在什么时间段上起作用。描述注解的生命周期。取值有如下几个(定义在java.lang.annotation.RetentionPolicy中):

1.SOURCE:源文件2.CLASS:class文件3.RUNTIME:运行时

平时我们用的比较多的值是RUNTIME,注解在运行时生效。

SOURCE 源代码阶段起作用CLASS 到编译阶段还能起作用RUNTIME 到运行期还能起作用

@Inherited

继承注解:当一个超类使用了这个注解,然后他的子类如果没有使用注解的话,那么子类可以继承超类的注解。

// 注解Apublic @interface A {}// 超类B@Apublic class B {}// B的子类Cpublic class C extends B {}

那么,C也拥有注解A。

@Repeatable

可重复的,当一个注解A使用了这个可重复的注解,那么注解A可以多次注解在同一个地方。

public @interface Colors {    Color[] value();}@Repeatable(Colors.class)public @interface Color {    String color() default "black";}@Color("purple")@Color("brown")@Color("red")public class Pen {}

上面这个代码块就是这个注解的习惯用法,自己理解哈。

注解的属性

注解只有属性,没有方法。注解的属性定义跟无形参的方法很像。

public @interface A {    // String 是属性的返回值,msg是属性的名称,可以用default后面跟着默认的值    String msg() default "msg";}

使用方式

@A(msg = "newday")public class B {}

如果注解属性中,只有一个属性,并且属性的名称为value那么可以直接在注解后面直接填值,不用写出属性名,如:

@C(value = "msg")//等价于@C("msg")

注解的运用

Class中有三个为注解提供的方法:

// 判断是否使用了注解public boolean isAnnotationPresent(Class extends Annotation> annotationClass) {}// 获取某个注解public  A getAnnotation(Class annotationClass) {}// 获取所有注解public Annotation[] getAnnotations() {}

例子-01:

@Newday(msg = "newday")public class App {    /**     * @description TODO     * @date 2018年1月31日 下午11:06:13     * @param args     */    public static void main(String[] args) throws Exception {        boolean flag = App.class.isAnnotationPresent(Newday.class);        if (flag) {            Newday newday = App.class.getAnnotation(Newday.class);            System.out.println("annotation: " + newday.msg());        }            }}

结果:

annotation: newday

PS:记得给注解Newday的作用时段设置为RetentionPolicy.RUNTIME哦,不然你可看不到输出的。还有就是,注解的提取是基于反射机制的,而反射是比较耗时的,所以使用注解的时候请考虑时间成本。

例子-02:

@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.FIELD})public @interface NotNull {    public String value() default "1234";}

上面是一个自定义的注解类,使用元注解来定义自定义注解,自定义注解的函数名就是参数名,函数返回类型是变量的类型。返回类型只能是基本类型、Class、Enum、String,可以通过default来声明参数的默认值。

下面来看下如何使用这个注解:

在类的定义中使用上面自定义的注解类:

public class TypeClass {    @NotNull    public int intType;    public String s;    @Override    public String toString() {        return "TypeClass{" +                "intType=" + intType +                ", s='" + s + ''' +                '}';    }}

使用上面定义的类:

TypeClass typeClass = new TypeClass();Field[] fields = TypeClass.class.getDeclaredFields();for (Field field : fields) {    NotNull annotation = field.getAnnotation(NotNull.class);    if(annotation != null) {        System.out.println(field.getName() + "  " +annotation);        System.out.println("CFNotNull value: " + annotation.value());    }}

上面的示例中可以拿到TypeClass的所有字段,然后逐个去判断字段的注解,根据自己定义的注解去做不同的逻辑操作。

总结

简单说,注解就是对程序的说明和预处理,提供一种规约化的处理机制。很多框架都把配置文件的相关内容直接给注解化,比如Spring框架和JavaEE实现等。