Introdução às Anotações em Java
As anotações em Java representam uma forma de metadados — informações adicionais sobre o código — que podem ser adicionadas a classes, métodos, campos, parâmetros e outros elementos. Elas não alteram diretamente o comportamento do programa, mas fornecem instruções e configurações para o compilador, ferramentas de build, frameworks ou o próprio código em tempo de execução.
As anotações ajudam a separar a configuração da lógica de negócio, tornando o código mais limpo, declarativo e fácil de manter. Elas são a base de diversas tecnologias modernas do ecossistema Java — como Spring, Jakarta EE, JUnit e Hibernate.
Estrutura e Sintaxe
Toda anotação começa com o símbolo @, seguido do nome da anotação:
@Override
public String toString() {
return "Pessoa";
}As anotações podem conter parâmetros, mas também podem ser usadas sozinhas. Por exemplo, uma anotação personalizada poderia ser usada assim:
@MyAnnotation
public class Person { }Tipos de anotações
As anotações podem ser classificadas em dois grandes grupos:
- Anotações de declaração (declaration annotations) — aplicadas a classes, métodos, construtores, variáveis, parâmetros, pacotes ou módulos.
- Anotações de uso de tipo (type-use annotations) — aplicadas diretamente a tipos (como genéricos, arrays, conversões de tipo, etc.).
Exemplos de anotações de declaração
As anotações podem ser aplicadas a diferentes elementos:
@MyAnnotation
public class User { }
@MyAnnotation
public void printName(@MyAnnotation String name) { }
record Person(@MyAnnotation String name) { }
class Example<@MyAnnotation T> { }Essas anotações informam que determinado elemento possui um marcador específico, que poderá ser processado por ferramentas ou frameworks.
Exemplos de anotações de uso de tipo
As type-use annotations permitem marcar o próprio tipo e podem ser aplicadas em contextos como:
Person<@MyAnnotation String> person;
String @MyAnnotation [] names;
new @MyAnnotation Person();
(@MyAnnotation String) text;
if (text instanceof @MyAnnotation String) { ... }Essas anotações não afetam a semântica do tipo, mas podem ser utilizadas para análises estáticas, validações ou geração de código.
Anotações padrão do Java
O Java já fornece diversas anotações embutidas que são amplamente usadas no dia a dia.
@Override
Indica que um método redefine um método da superclasse. Se o método não corresponder exatamente a nenhum da classe pai, o compilador gerará erro — evitando falhas por erro de digitação.
Exemplo sem @Override (erro silencioso):
class Animal {
void makeSound() {
System.out.println("Som genérico");
}
}
class Cat extends Animal {
void makeSounds() { // erro de digitação!
System.out.println("Miau");
}
}
public class Program {
public static void main(String[] args) {
Cat cat = new Cat();
cat.makeSound(); // saída: Som genérico
}
}Com @Override:
class Cat extends Animal {
@Override
void makeSounds() { // agora o compilador detecta o erro
System.out.println("Miau");
}
}Resultado:
error: method does not override or implement a method from a supertype
Isso força o desenvolvedor a corrigir o nome do método — evitando comportamentos incorretos em tempo de execução.
@Deprecated
Marca um elemento (método, classe, campo) como obsoleto — ou seja, não deve mais ser utilizado. O compilador exibirá um aviso (warning) sempre que o elemento for usado.
class Cat {
@Deprecated
void makeSound() {
System.out.println("Miau");
}
void say() {
System.out.println("Miau");
}
}
public class Program {
public static void main(String[] args) {
Cat cat = new Cat();
cat.makeSound(); // warning: método obsoleto
}
}Saída do compilador:
warning: [deprecation] makeSound() in Cat has been deprecated
@SuppressWarnings
Usada para suprimir avisos do compilador em um trecho de código específico. Por exemplo, para ignorar o aviso de uso de tipo cru (raw type):
import java.util.ArrayList;
import java.util.List;
class Program {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List names = new ArrayList(); // tipo cru
names.add("Tom");
System.out.println(names);
}
}Sem essa anotação, o compilador emitiria um warning sobre a falta de tipo genérico (List<String>).
@FunctionalInterface
Indica que uma interface é funcional, ou seja, deve conter apenas um método abstrato. É muito utilizada em programação funcional e com expressões lambda.
@FunctionalInterface
interface MyComparator {
int compare(String a, String b);
}Se você tentar adicionar outro método abstrato, o compilador emitirá erro.
Resumo
| Anotação | Propósito | Efeito principal |
|---|---|---|
@Override | Garante que o método redefine um da superclasse | Evita erros de digitação |
@Deprecated | Marca elementos como obsoletos | Exibe aviso de depreciação |
@SuppressWarnings | Suprime avisos do compilador | Evita alertas em código legado |
@FunctionalInterface | Declara uma interface funcional | Exige apenas um método abstrato |
Conclusão
As anotações são um dos pilares da metaprogramação em Java. Elas permitem declarar intenções de forma declarativa e não invasiva, simplificando a configuração e integrando o código a frameworks modernos. Embora, por si só, não alterem o comportamento do programa, seu poder reside nos processadores de anotações — mecanismos que interpretam e agem com base nesses metadados.