Java注释

时间:2020-01-09 10:35:41  来源:igfitidea点击:

Java注释(批注)用于为Java代码提供元数据。 Java注释是元数据,它并不直接影响代码的执行,尽管某些类型的注释实际上可以用于此目的。

Java注释已从Java 5添加到Java。此文本涵盖了Java注释在Java 8,Java 9及更高版本中的外观。据我所知,Java注释在更高的Java版本中没有更改,因此该文本也应适用于Java 8、9、10和11程序员。

Java注释目的

Java批注通常用于以下目的:

  • 编译指令
  • 建立时间指示
  • 运行时说明

Java具有3个内置注释,可用于向Java编译器提供指令。这些注释将在本文后面详细说明。

在构建软件项目时,可以在构建时使用Java批注。构建过程包括生成源代码,编译源代码,生成XML文件(例如,部署描述符),将编译后的代码和文件打包到JAR文件中等。构建软件通常由自动构建工具(如Apache Ant或者Apache Maven)完成。 。生成工具可能会扫描Java代码中的特定注释,并根据这些注释生成源代码或者其他文件。

通过Java反射访问Java批注

通常,编译后Java注释不会出现在Java代码中。但是,可以定义自己的注释,这些注释在运行时可用。然后可以通过Java Reflection来访问这些批注,并用于为程序或者某些第三方API提供指令。我已经在我的Java Reflection and Annotations教程中介绍了如何通过反射访问Java注释。

基本注释

最短形式的Java注释如下所示:

@Entity

" @"字符向编译器表示这是一个注释。 @字符后的名称是注释的名称。在上面的示例中,注释名称为"实体"。

注释元素

Java批注可以包含我们可以为其设置值的元素。元素就像属性或者参数。这是带有元素的Java注释的示例:

@Entity(tableName = "vehicles")

此示例中的注释包含一个名为" tableName"的元素,其值设置为" vehicles"。元素被括在注释名称后的括号内。没有元素的注释不需要括号。

注释可以包含多个元素。这是一个多元素Java注释示例:

@Entity(tableName = "vehicles", primaryKey = "id")

如果注释仅包含单个元素,则习惯上将该元素命名为"值",如下所示:

@InsertNew(value = "yes")

当注释仅包含一个名为"值"的元素时,我们可以省略元素名称,而仅提供值。这是仅提供值的注释元素的示例:

@InsertNew("yes")

注释放置

我们可以在类,接口,方法,方法参数,字段和局部变量上方放置Java注释。这是在类定义上方添加的示例注释:

@Entity
public class Vehicle {
}

注释以" @"字符开头,后跟注释的名称。在这种情况下,注释名称为"实体"。实体注解是我制作的注解。在Java中没有任何意义。

这是一个更大的示例,在类,字段,方法,参数和局部变量上方都带有注释:

@Entity
public class Vehicle {

    @Persistent
    protected String vehicleName = null;

    @Getter
    public String getVehicleName() {
        return this.vehicleName;
    }

    public void setVehicleName(@Optional vehicleName) {
        this.vehicleName = vehicleName;
    }

    public List addVehicleNameToList(List names) {

        @Optional
        List localNames = names;

        if(localNames == null) {
            localNames = new ArrayList();
        }
        localNames.add(getVehicleName());

        return localNames;
    }

}

批注再次只是我制作的批注。它们在Java中没有特定的含义。

内置Java注释

Java带有三个内置注释,用于向Java编译器提供指令。这些注释是:

  • @已弃用
  • @Override
  • @SuppressWarnings

以下各节将对这些注释中的每一个进行解释。

@Deprecated

@Deprecated批注用于将类,方法或者字段标记为已弃用,这意味着不应再使用它。如果代码使用了不赞成使用的类,方法或者字段,则编译器将向我们发出警告。这是@Deprecated Java注释示例:

@Deprecated
public class MyComponent {

}

在类声明上方使用Java批注@Deprecated将该类标记为已弃用。

我们还可以使用方法和字段声明上方的@Deprecated批注,将方法或者字段标记为已弃用。

当使用@ Deprecated注释时,最好也使用相应的@ deprecatedJavaDoc符号,并说明为什么不赞成使用类,方法或者字段以及程序员应该使用什么。例如:

@Deprecated
/**
  @deprecated Use MyNewComponent instead.
*/
public class MyComponent {

}

@Override

上面的方法使用了@Override Java注释,这些方法将覆盖超类中的方法。如果该方法与超类中的方法不匹配,则编译器将给我们一个错误。

为了覆盖超类中的方法,不需要@Override注释。不过,仍然使用它是一个好主意。如果有人在超类中更改了覆盖方法的名称,则子类方法将不再覆盖它。没有@ Override注释,我们将找不到答案。使用@Override批注,编译器会告诉我们子类中的方法不会覆盖超类中的任何方法。

这是一个@Override Java注释示例:

public class MySuperClass {

    public void doTheThing() {
        System.out.println("Do the thing");
    }
}

public class MySubClass extends MySuperClass{

    @Override
    public void doTheThing() {
        System.out.println("Do it differently");
    }
}

如果MySuperClass中的doTheThing()方法更改了签名,以使子类中的相同方法不再覆盖它,则编译器将生成错误。

@SuppressWarnings

@SuppressWarnings批注使编译器抑制给定方法的警告。例如,如果某个方法调用了不赞成使用的方法,或者进行了不安全的类型转换,则编译器可能会生成警告。我们可以通过使用@SuppressWarnings注释对包含代码的方法进行注释,从而消除这些警告。

这是一个@SuppressWarnings Java注释示例:

@SuppressWarnings
public void methodWithWarning() {

}

创建自己的Java注释

可以创建自己的(自定义)Java批注。注释在它们自己的文件中定义,就像Java类或者接口一样。顺便说一下,我已经创建了一个有关创建自己的Java批注的视频教程。我们可以在本段下面找到它。如果我们希望使用文字说明,只需向下滚动视频并继续阅读即可。

创建自己的Java注释视频教程

自定义Java注释示例

这是自定义Java注释示例:

@interface MyAnnotation {

    String   value();

    String   name();
    int      age();
    String[] newNames();

}

这个例子定义了一个名为" MyAnnotation"的注释,它包含四个元素。注意" @interface"关键字。这会向Java编译器发出信号,这是Java注释定义。

注意,每个元素的定义都类似于接口中的方法定义。它具有数据类型和名称。我们可以将所有原始数据类型用作元素数据类型。我们也可以使用数组作为数据类型。我们不能将复杂的对象用作数据类型。

要使用上面的注释,可以使用如下代码:

@MyAnnotation(
    value="123",
    name="Hyman",
    age=37,
    newNames={"Hyman", "Peterson"}
)
public class MyClass {

}

如我们所见,我必须为MyAnnotation批注的所有元素指定值。

元素默认值

我们可以为元素指定默认值。这样,该元素就成为可选元素,并且可以省略。这是一个注释定义的外观示例,该注释定义具有元素的默认值:

@interface MyAnnotation {

    String   value() default "";

    String   name();
    int      age();
    String[] newNames();

}

现在可以在使用注释时忽略"值"元素。如果我们将其保留,则将其视为我们已对value元素使用了默认值。这是一个注释的示例,其中元素值被忽略,因此该元素被设置为默认值:

@MyAnnotation(
    name="Hyman",
    age=37,
    newNames={"Hyman", "Peterson"}
)
public class MyClass {

}

注意,"值"元素不再存在。

@Retention

我们可以为自定义注释指定是否应在运行时可用,以通过反射进行检查。我们可以通过使用@Retention批注对批注定义进行批注来实现。这是完成的方式:

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

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation {

    String   value() default "";

}

注意在MyAnnotation定义上方添加的@Retention注释:

@Retention(RetentionPolicy.RUNTIME)

这就是向Java编译器和JVM发出信号的提示,即注释应该在运行时通过反射可用。我的Java Reflection and Annotations教程中涵盖了在运行时访问注释,这是Java Reflection教程的一部分。

RetentionPolicy类包含两个可以使用的值:

RetentionPolicy.CLASS表示注释存储在.class文件中,但在运行时不可用。如果我们根本没有指定任何保留策略,则这是默认的保留策略。

RetentionPolicy.SOURCE表示注释仅在源代码中可用,而在.class文件和运行时中不可用。如果我们创建自己的注释以与扫描代码的构建工具一起使用,则可以使用此保留策略。这样,.class文件就不会受到不必要的污染。

@Target

我们可以指定自定义注释可用于注释哪些Java元素。为此,可以使用@Target批注对批注定义进行批注。这是一个@Target Java注释示例:

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

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

    String   value();
}

此示例显示了Java注释,该注释只能用于对方法进行注释。

ElementType类包含以下可能的目标:

  • ElementType.ANNOTATION_TYPE
  • ElementType.CONSTRUCTOR
  • ElementType.FIELD
  • ElementType.LOCAL_VARIABLE
  • ElementType.METHOD
  • ElementType.PACKAGE
  • ElementType.PARAMETER
  • ElementType.TYPE

其中大多数是自我解释,但有一些不是。因此,我将说明目标不明确的目标。

" ANNOTATION_TYPE"目标表示Java注释定义。因此,注释只能用于注释其他注释。就像@Target和@Retention注释一样。

" TYPE"目标表示任何类型。类型可以是类,接口,枚举或者注释。

@Inherited

" @Inherited"注释表示从该类继承的子类应继承该类中使用的自定义Java注释。这是一个@Inherited Java注释示例:

java.lang.annotation.Inherited

@Inherited
public @interface MyAnnotation {

}
@MyAnnotation
public class MySuperClass { ... }
public class MySubClass extends MySuperClass { ... }

在这个例子中,类MySubClass继承了注解@MyAnnotation,因为MySubClass继承了MySuperClass,而MySuperClass具有@MyAnnotation注释。

@Documented

@Documented注解用于向JavaDoc工具发出信号,表明使用自定义注释的类的自定义注释应在JavaDoc中可见。这是一个@Documented Java注释示例:

import java.lang.annotation.Documented;

@Documented
public @interface MyAnnotation {

}
@MyAnnotation
public class MySuperClass { ... }

在为MySuperClass类生成JavaDoc时,JavaDoc中现在包含了@MyAnnotation。

我们不会经常使用@ Documented注释,但是现在我们知道它是否存在,如果需要的话。