Em 2005, com a chegada do Java 5, passamos a conhecer novas entidades chamadas de anotações.

As anotações são uma forma especial de metadados sintáticos que podem ser declarados no código. Eles são usados ​​para analisar o código na compilação ou no tempo de execução. Você pode pensar em uma anotação como um rótulo, tag ou dica do compilador.

Você provavelmente já encontrou anotações antes. Por exemplo, ao sobrescrever um método da classe pai, escrevemos @Override antes do próprio método. Essa anotação indica que o método do pai será substituído na classe filha.

Sintaxe:


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

Quero observar imediatamente que as anotações não se aplicam apenas aos métodos. Eles são usados ​​com pacotes, classes, métodos, campos e parâmetros.

Para entender como as anotações funcionam, primeiro vamos nos familiarizar com o conceito de interface de marcador. Desde o advento do Java, os desenvolvedores sempre precisaram de uma maneira de marcar as classes para realizar determinadas ações nelas.

Antes do Java 5, eles usavam uma interface que não fazia o que esperávamos que as interfaces fizessem. Não tinha métodos nem contrato. Apenas marcou uma aula como especial de alguma forma.

Essa interface foi chamada de interface de marcador. Pelo nome, você pode imaginar que seu propósito é marcar classes para a JVM, compilador ou alguma biblioteca. Algumas interfaces de marcador, como Serializable , permanecem. Essa interface de marcador nos permite indicar que as instâncias de uma classe podem ser serializadas.

Como vimos, as interfaces de marcadores continuam vivas mesmo após a introdução das anotações.

Anotações versus interfaces de marcadores:


@MyAnnotation
public class MyClass {}

public class MyClass implements MarkerInterface {}

Ambas as abordagens têm o mesmo objetivo, mas há uma clara diferença em sua implementação. Por exemplo, considere uma interface e uma anotação que indica que uma classe pertence a um determinado tipo.

Se estivermos usando uma interface, marcamos a classe. Se o usarmos incorretamente e ocorrer um erro, descobriremos o problema na compilação e o programa não será executado.

Com anotações, nem tudo é tão simples: aqui o erro será detectado em tempo de execução, o que significa que o programa iniciará, mas, sem surpresa, não terminará.

Observe que se precisarmos marcar uma classe para uso futuro, suas instâncias devem ser passadas para um método específico:


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
}

Uma interface de marcador funciona melhor aqui.

É melhor usar anotações quando precisamos de algo mais, como os parâmetros que as anotações suportam.

Vejamos as anotações padrão no JDK:

Anotação Descrição Exemplo
@Sobrepor Especifica que um método substitui o método de uma superclasse ou implementa um método de uma classe abstrata ou interface.

@Override
public int hashCode() {
        return super.hashCode();
}
@Descontinuada Marca o código como obsoleto.

@Deprecated
public abstract void method();
@Suprimir avisos Desativa os avisos do compilador para o elemento anotado. Observe que, se você precisar desabilitar várias categorias de avisos, elas devem ser colocadas entre chaves, por exemplo @SuppressWarnings({"unchecked", "cast"}) .

public class DocumentsFolder {
   private List documents;

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

Neste exemplo, estamos tentando adicionar a uma lista que não possui um tipo definido (um tipo genérico). O compilador nos avisará sobre isso. Isso é muito útil, mas às vezes há muitos "avisos" e eles podem ser barulhentos. Você pode usar essa anotação de método e especificar um tipo de aviso do compilador como um argumento. Existem muitos marcadores, então não se preocupe em lembrar de todos eles — o IDEA geralmente lhe dirá qual adicionar.

Outro exemplo com vários argumentos:


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