# 带有示例的 Java Annotations 教程

> 原文： [https://beginnersbook.com/2014/09/java-annotations/](https://beginnersbook.com/2014/09/java-annotations/)

[Java Annotations](https://docs.oracle.com/javase/tutorial/java/annotations/index.html) 允许我们将元数据信息添加到我们的源代码中，尽管它们不是程序本身的一部分。注释从 JDK 5 添加到 java 中。注释对它们注释的代码的操作没有直接影响（即它不影响程序的执行）。

在本教程中，我们将介绍以下主题：注释的使用，如何应用注释，Java 中可用的预定义注释类型以及如何创建自定义注释。

## 注释有什么用？

**1）编译器指令**：Java 中有三种内置注释（`@Deprecated`，`@Override`＆amp; `@SuppressWarnings`），可用于向编译器提供某些指令。例如，@ override 注释用于指示编译器注释方法是否覆盖该方法。有关这些内置注释的更多信息，请参阅本文的下一部分。

**2）编译时教程**：注释可以为编译器提供编译时指令，软件构建工具可以进一步使用它来生成代码，XML 文件等。

**3）运行时指令**：我们可以定义在运行时可用的注释，我们可以使用 [java 反射](https://docs.oracle.com/javase/tutorial/reflect/)访问它们，并可用于在运行时向程序发出指令。我们将在稍后的同一篇文章的帮助下讨论这个问题。

## 注释基础知识

注释始终以符号`@`开头，后跟注释名称。符号`@`向编译器指示这是一个注释。

对于例如`@Override`
这里@符号表示这是一个注释，而 Override 是这个注释的名称。

**我们可以在哪里使用注释？**
注释可以应用于类，接口，方法和字段。例如，以下注释正在应用于该方法。

```java
@Override
void myMethod() { 
    //Do something 
}
```

这个注释在这里做的正是在下一节中解释的，但简单来说它指示编译器`myMethod()`是一个覆盖超类方法（myMethod（））的重写方法。

## Java 中的内置注释

Java 有三个内置注释：

*   @覆盖
*   @Deprecated
*   @SuppressWarnings

#### 1）@Override：

在覆盖子类中的方法时，我们应该使用此批注来标记该方法。这使得代码可读并避免维护问题，例如：在更改父类的方法签名时，必须更改子类中的签名（使用此批注的位置），否则编译器将抛出编译错误。如果您没有使用此注释，则很难跟踪。

例：

```java
public class MyParentClass {

    public void justaMethod() {
        System.out.println("Parent class method");
    }
}

public class MyChildClass extends MyParentClass {

    @Override
    public void justaMethod() {
        System.out.println("Child class method");
    }
}
```

我相信这个例子是自我解释的。要阅读有关此注释的更多信息，请参阅以下文章： [@Override 内置注释](https://beginnersbook.com/2014/07/override-annotation-in-java/ "@Override annotation in Java")。

#### 2）@Deprecated

@Deprecated 注释表示已弃用标记的元素（类，方法或字段），不应再使用。只要程序使用已经使用@Deprecated 注释标记的方法，类或字段，编译器就会生成警告。不推荐使用元素时，也应使用 Javadoc @deprecated 标记对其进行记录，如以下示例所示。记下@Deprecated 和@deprecated 的大小写差异。 @deprecated 用于文档目的。

Example:

```java
/**
 * @deprecated
 * reason for why it was deprecated
 */
@Deprecated
public void anyMethodHere(){
    // Do something
}
```

现在，只要任何程序使用此方法，编译器就会生成警告。要阅读有关此注释的更多信息，请参阅以下文章： [Java - @Deprecated annotation](https://beginnersbook.com/2014/07/deprecated-annotation-in-java/ "@Deprecated annotation in java") 。

#### 3）@SuppressWarnings

此批注指示编译器忽略特定警告。例如，在下面的代码中，我调用了一个不推荐使用的方法（假设方法 deprecatedMethod（）标有@Deprecated 注释），因此编译器应该生成警告，但是我使用@@ SuppressWarnings 注释来抑制弃用警告。

```java
@SuppressWarnings("deprecation")
    void myMethod() {
        myObject.deprecatedMethod();
}
```

## 创建自定义注释

*   注释是使用@interface 创建的，后跟注释名称，如下例所示。
*   注释也可以包含元素。他们看起来像方法。例如，在下面的代码中，我们有四个元素。我们不应该为这些元素提供实现。
*   所有注释都扩展了 java.lang.annotation.Annotation 接口。注释不能包含任何 extends 子句。

```java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation{
    int studentAge() default 18;
    String studentName();
    String stuAddress();
    String stuStream() default "CSE";
}
```

注意：使用注释时，可以跳过在创建注释时设置了默认值的所有元素。例如，如果我将上述注释应用于类，那么我会这样做：

```java
@MyCustomAnnotation(
    studentName="Chaitanya",
    stuAddress="Agra, India"
)
public class MyClass {
...
}
```

如您所见，我们没有给`studentAge`和`stuStream`元素赋予任何值，因为设置这些元素的值是可选的（默认值已经在注释定义中设置，但是如果您希望可以分配新的使用注释时的值与我们对其他元素的处理方式相同）。但是，我们必须在使用注释时提供其他元素的值（没有设置默认值的元素）。

**注意**：我们也可以在注释中包含数组元素。这就是我们如何使用它们：
注释定义：

```java
@interface MyCustomAnnotation {
    int      count();
    String[] books();
}
```

用法：

```java
@MyCustomAnnotation(
    count=3,
    books={"C++", "Java"}
)
public class MyClass {

}
```

再次回到主题：在自定义注释示例中，我们使用了这四个注释：`@Documented`，`@Target`，`@Inherited`＆amp; `@Retention`。让我们详细讨论它们。

#### @Documented

@Documented 注释表明使用此注释的元素应由 JavaDoc 记录。例如：

```java
java.lang.annotation.Documented
@Documented
public @interface MyCustomAnnotation {
  //Annotation body
}
```

```java
@MyCustomAnnotation
public class MyClass { 
     //Class body
}
```

在为类`MyClass`生成 javadoc 时，注释`@MyCustomAnnotation`将包含在其中。

#### @目标

它指定了我们可以使用注释的位置。例如：在下面的代码中，我们将目标类型定义为 METHOD，这意味着下面的注释只能用于方法。

```java
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
public @interface MyCustomAnnotation {

}
```

```java
public class MyClass {
   @MyCustomAnnotation
   public void myMethod()
   {
       //Doing something
   }
}
```

**注意**：1）如果您没有定义任何目标类型，则意味着可以将注释应用于任何元素。
2）除了 ElementType.METHOD 之外，注释可以具有以下可能的 Target 值。
ElementType.METHOD
ElementType.PACKAGE
ElementType.PARAMETER
ElementType.TYPE
ElementType.ANNOTATION_TYPE
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.FIELD

#### @遗传

@Inherited 注释表示类中使用的自定义注释应该由其所有子类继承。例如：

```java
java.lang.annotation.Inherited

@Inherited
public @interface MyCustomAnnotation {

}
```

```java
@MyCustomAnnotation
public class MyParentClass { 
  ... 
}
```

```java
public class MyChildClass extends MyParentClass { 
   ... 
}
```

这里的类`MyParentClass`正在使用注释`@MyCustomAnnotation`，该注释用@inherited 注释标记。这意味着子类`MyChildClass`继承了`@MyCustomAnnotation`。

#### @保留

它指示要保留带注释类型的注释的时间长度。

```java
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@interface MyCustomAnnotation {

}
```

这里我们使用了 RetentionPolicy.RUNTIME。还有另外两种选择。让我们看看他们的意思：
`RetentionPolicy.RUNTIME`：注释应该在运行时可用，以便通过 java 反射进行检查。
`RetentionPolicy.CLASS`：注释将在.class 文件中，但在运行时不可用。
`RetentionPolicy.SOURCE`：注释将在程序的源代码中提供，它既不在.class 文件中，也不在运行时可用。

这就是“Java Annotation”这个主题的全部内容。如果您有任何疑问，请随时在下面留言。