理解 Java 注解 – Java @annotations 教程
已发表: 2019-10-22
Java 中如何以及在何处使用注解?
在 Java 计算机编程语言中,注解是一种特殊形式的句法元数据,可以添加到 Java 源代码中。
类、方法、变量、参数和包可以被注释。 与 Javadoc 标记不同,Java 注释可以是反射性的,因为它们可以嵌入编译器生成的类文件中,并且可以由 Java VM 保留,以便在运行时进行检索。
可以从 Java 中现有的元注释中创建元注释,这使得这个概念更加复杂。
Java 定义了一组内置于语言中的注释。

应用于java代码的注释:
- @Override – 检查函数是否为覆盖。 如果在其中一个父类中找不到该函数,则会导致编译警告。
- @Deprecated – 将函数标记为已过时。 如果使用该函数,则会导致编译警告。
- @SuppressWarnings – 指示编译器抑制注释参数中指定的编译时警告。
应用于其他注释的注释:
- @Retention – 指定标记注解的存储方式——无论是仅在代码中、编译到类中还是在运行时通过反射可用。
- @Documented – 标记另一个注释以包含在文档中。
- @Target – 标记另一个注解以限制该注解可以应用到的 Java 元素类型。
- @Inherited - 将另一个注解标记为继承到被注解的类的子类(默认情况下注解不会被继承到子类)。
让我们通过示例来看看这些:
1)@Override注解:
它的存在向编译器表明带注释的方法必须覆盖现有的超类方法。
@Override最常见的用例是使用Object方法:
1 2 3 4 |
@ Override public int hashValue ( ) { System . out . Println ( "This method is using @Override Annotation" ) ; } |
创建@Override的主要原因是为了处理简单的印刷错误。
例如,一个方法被错误地声明为
1 |
public int hashvalue ( ) { . . . } |
实际上不是覆盖 - 方法名称全是小写字母,因此它与hashValue()方法的名称不完全匹配。 然而,它会编译得很好。 这样的错误很容易犯,也很难捕捉,这是一个危险的组合。 使用@Override注释可防止您犯此类错误。
每当您覆盖超类方法时,您应该养成使用@Override的习惯。

2)@Deprecated注解:
此注释表明标记的元素已被弃用,不应再使用。 每当程序使用带有@Deprecated
注释的方法、类或字段时,编译器都会生成警告。
当一个元素被弃用时,还应该使用 Javadoc @deprecated
标记对其进行记录,如以下示例所示。
1 2 3 4 |
< strong > @ Deprecated < / strong > static void deprecatedMethod ( ) { System . out . Println ( "This method is Deprecated.." ) ; } |
3)@SuppressWarnings 注释:
只是告诉编译器,请不要大喊大叫。 我知道我在做什么。
1 2 3 4 |
@ SuppressWarnings ( "serial" ) public class OldCode implements Serializable { System . out . Println ( "This is Old Code.." ) ; } |
4)@Retention注解:
保留注释指示将在何处保留此类型的注释以及保留多长时间。
有三个值:
- RetentionPolicy.SOURCE — 这种类型的注解将只保留在源代码级别,编译器会忽略它。
- RetentionPolicy.CLASS — 编译器会在编译时保留此类型的注解,但会被 VM 忽略。
- RetentionPolicy.RUNTIME — VM 将保留此类型的注释,因此它们只能在运行时读取。
1 2 3 4 |
@ Retention ( RetentionPolicy . RUNTIME ) public @ interface Crunchify_Retention { String returnSomething ( ) ; } |
5)@记录注释:
1 2 3 4 |
@ Documented public @ interface Crunchify_Documented { String writeDocument ( ) ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class DocumentedAnnotations { public static void main ( String arg [ ] ) { new DocumentedAnnotations ( ) . performRetention ( ) ; new DocumentedAnnotations ( ) . performDocumented ( ) ; } @ Crunchify_Retention ( returnSomething = "Hello retention test" ) public void performRetention ( ) { System . out . printf ( "Testing annotation 'Crunchify_Retention'" ) ; } @ Crunchify_Documented ( writeDocument = "Hello document" ) public void performDocumented ( ) { System . out . printf ( "Testing annotation 'Crunchify_Documented'" ) ; } } |
现在尝试运行 Java Doc 命令并查看输出。

6)@Target注解:
目标指示可以使用带注释的注释类型的实例来注释哪些程序元素。 Target 的值是java.lang.annotation.ElementType
枚举的成员之一:
- ANNOTATION_TYPE。 带注释的注释类型可用于注释注释类型声明。
- 构造函数。 带注释的注释类型可用于注释构造函数声明。
- 场地。 带注释的注释类型可用于注释字段声明。
- 本地变量。 带注释的注释类型可用于注释局部变量声明。
- 方法。 带注释的注释类型可用于注释方法声明。
- 包裹。 带注释的注释类型可用于注释包声明。
- 范围。 带注释的注释类型可用于注释参数声明。
- 类型。 带注释的注释类型可用于注释类型声明。
1 2 3 4 |
@ Target ( value = METHOD ) You can have multiple values in the Target annotation . @ Target ( value = { TYPE , FIELD , METHOD , PARAMETER , CONSTRUCTOR , LOCAL_VARIABLE } ) |
7)@Inherited注解:
顾名思义, @Inherited
注解类型由注解类型的子类继承。
1 2 3 4 5 6 7 8 9 10 |
@ Inherited @ interface ForEveryone { } @ interface JustForMe { } @ ForEveryone @ JustForMe class Superclass { } class Subclass extends Superclass { } |
在这个例子中, Superclass
已经被明确地注释了@ForEveryone
和@JustForMe
。 Subclass
没有被明确标记为任何一个; 但是,它继承@ForEveryone
,因为后者带有@Inherited
注释。
@JustForMe
没有注释,所以它没有被Subclass
继承。
这是一个类级别的注释
