2005 年,随着 Java 5 的到来,我们开始了解称为注解的新实体。

注释是一种特殊形式的语法元数据,可以在代码中声明。它们用于在编译或运行时分析代码。您可以将注释视为标签、标记或编译器提示。

您之前可能遇到过注释。比如重写父类的一个方法,我们在方法本身之前写上@Override 。该注解表明父类的方法将在子类中被覆盖。

句法:

@Override
public int hashCode() {
      return super.hashCode();
}

我想立即指出注释不仅仅适用于方法。它们与包、类、方法、字段和参数一起使用。

要了解注释的工作原理,让我们首先熟悉标记接口的概念。自从 Java 出现以来,开发人员一直需要一种方法来标记类,以便对它们执行某些操作。

在 Java 5 之前,他们使用的接口没有做我们期望接口做的事情。它没有方法,也没有契约。它只是以某种方式将一个类标记为特殊的。

这样的接口被称为标记接口。从名字你可能猜到它的目的是为 JVM、编译器或一些库标记类。保留了一些标记接口,例如Serializable。这个标记接口让我们表明一个类的实例可以被序列化。

正如我们所见,即使在引入注解之后,标记接口仍然存在。

注释与标记接口:

@MyAnnotation
public class MyClass {}
public class MyClass implements MarkerInterface {}

两种方法都有相同的目标,但它们的实现有明显的区别。例如,考虑一个接口和一个指示类属于特定类型的注释。

如果我们正在使用一个接口,那么我们就标记这个类。如果我们使用不当,出现错误,那么我们会在编译时发现问题,程序将无法运行。

有了注解,一切就不那么简单了:这里会在运行时检测到错误,这意味着程序会启动,但不出所料,它不会完成。

请注意,如果我们需要标记一个类以供将来使用,则必须将其实例传递给特定方法:

public class MyInteger implements Sum {}
interface Sum {};

public static void main(String[] args) throws IOException {
        increase(new MyInteger());
}

public static void increase(Sum count) {
        // TODO
}

标记界面在这里效果最好。

当我们需要更多东西的时候最好使用注解,比如注解支持的参数。

我们来看看JDK中的标准注解:

注解 描述 例子
@覆盖 指定方法覆盖超类的方法或实现抽象类或接口的方法。
@Override
public int hashCode() {
        return super.hashCode();
}
@弃用 将代码标记为已弃用。
@Deprecated
public abstract void method();
@SuppressWarnings 为带注释的元素禁用编译器警告。请注意,如果您需要禁用多个类别的警告,则必须将它们括在花括号中,例如@SuppressWarnings({"unchecked", "cast"})
public class DocumentsFolder {
   private List documents;

   @SuppressWarnings("unchecked")
public void addDocument(String document) {
            documents.add(document);
   }
}

在这个例子中,我们试图添加到一个没有定义类型(泛型)的列表中。编译器会警告我们这一点。这非常有用,但有时“警告”太多,它们可能会很吵。您可以使用此方法注释并指定一种编译器警告作为参数。有很多标记,所以不用担心全部记住它们——IDEA 通常会告诉您要添加哪一个。

另一个有多个参数的例子:

@SuppressWarnings({"unchecked", "deprecated"})