Tipos de anotação Java
Tipos de anotação Java
Neste tutorial, aprenderemos sobre diferentes tipos de anotação Java com a ajuda de exemplos.
As anotações Java são metadados (dados sobre dados) para o código-fonte do nosso programa. Existem várias anotações predefinidas fornecidas pelo Java SE. Além disso, também podemos criar anotações personalizadas conforme nossas necessidades.
Se você não sabe o que são anotações, visite o tutorial de anotações Java.
Essas anotações podem ser classificadas como:
1. Anotações predefinidas
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
2. Anotações personalizadas
3. Meta-anotações
@Retention
@Documented
@Target
@Inherited
@Repeatable
Tipos de anotação predefinidos
1. @Descontinuado
O
@Deprecated
annotation é uma anotação de marcador que indica que o elemento (classe, método, campo, etc.) está obsoleto e foi substituído por um elemento mais recente. Sua sintaxe é:
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }
Quando um programa usa o elemento que foi declarado obsoleto, o compilador gera um aviso.
Usamos Javadoc
@deprecated
tag para documentar o elemento obsoleto.
/**
* @deprecated
* why it was deprecated
*/
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }
Exemplo 1:@Exemplo de anotação obsoleta
class Main {
/**
* @deprecated
* This method is deprecated and has been replaced by newMethod()
*/
@Deprecated
public static void deprecatedMethod() {
System.out.println("Deprecated method");
}
public static void main(String args[]) {
deprecatedMethod();
}
}
Saída
Deprecated method
2. @Substituir
O
@Override
anotação especifica que um método de uma subclasse substitui o método da superclasse com o mesmo nome de método, tipo de retorno e lista de parâmetros. Não é obrigatório usar
@Override
ao substituir um método. No entanto, se o usarmos, o compilador dará um erro se algo estiver errado (como o tipo de parâmetro errado) ao substituir o método. Exemplo 2:exemplo de anotação @Override
class Animal {
// overridden method
public void display(){
System.out.println("I am an animal");
}
}
class Dog extends Animal {
// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}
public void printMessage(){
display();
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
Saída
I am a dog
Neste exemplo, fazendo um objeto dog1 de Cão classe, podemos chamar seu método printMessage() que então executa o
display()
declaração. Desde
display()
é definido em ambas as classes, o método da subclasse Dog sobrescreve o método da superclasse Animal . Portanto, o display()
da subclasse é chamado. 3. @SuppressWarnings
Como o nome sugere, o
@SuppressWarnings
A anotação instrui o compilador a suprimir os avisos gerados durante a execução do programa. Podemos especificar o tipo de avisos a serem suprimidos. Os avisos que podem ser suprimidos são específicos do compilador, mas há duas categorias de avisos:suspensão e desmarcado .
Para suprimir uma determinada categoria de aviso, usamos:
@SuppressWarnings("warningCategory")
Por exemplo,
@SuppressWarnings("deprecated")
Para suprimir várias categorias de avisos, usamos:
@SuppressWarnings({"warningCategory1", "warningCategory2"})
Por exemplo,
@SuppressWarnings({"deprecated", "unchecked"})
Categoria
deprecated
instrui o compilador a suprimir avisos quando usamos um elemento obsoleto. Categoria
unchecked
instrui o compilador a suprimir avisos quando usamos tipos brutos. E, avisos indefinidos são ignorados. Por exemplo,
@SuppressWarnings("someundefinedwarning")
Exemplo 3:exemplo de anotação @SuppressWarnings
class Main {
@Deprecated
public static void deprecatedMethod() {
System.out.println("Deprecated method");
}
@SuppressWarnings("deprecated")
public static void main(String args[]) {
Main depObj = new Main();
depObj. deprecatedMethod();
}
}
Saída
Deprecated method
Aqui,
deprecatedMethod()
foi marcado como obsoleto e dará avisos ao compilador quando usado. Usando o @SuppressWarnings("deprecated")
anotação, podemos evitar avisos do compilador. 4. @SafeVarargs
O
@SafeVarargs
annotation afirma que o método ou construtor anotado não executa operações inseguras em seus varargs (número variável de argumentos). Só podemos usar essa anotação em métodos ou construtores que não podem ser substituídos. Isso ocorre porque os métodos que os substituem podem realizar operações inseguras.
Antes do Java 9, podíamos usar essa anotação apenas em métodos finais ou estáticos porque eles não podem ser substituídos. Agora também podemos usar essa anotação para métodos privados.
Exemplo 4:exemplo de anotação @SafeVarargs
import java.util.*;
class Main {
private void displayList(List<String>... lists) {
for (List<String> list : lists) {
System.out.println(list);
}
}
public static void main(String args[]) {
Main obj = new Main();
List<String> universityList = Arrays.asList("Tribhuvan University", "Kathmandu University");
obj.displayList(universityList);
List<String> programmingLanguages = Arrays.asList("Java", "C");
obj.displayList(universityList, programmingLanguages);
}
}
Avisos
Type safety: Potential heap pollution via varargs parameter lists Type safety: A generic array of List<String> is created for a varargs parameter
Saída
Note: Main.java uses unchecked or unsafe operations. [Tribhuvan University, Kathmandu University] [Tribhuvan University, Kathmandu University] [Java, C]
Aqui,
List
... lists
especifica um argumento de comprimento variável do tipo List
. Isso significa que o método displayList()
pode ter zero ou mais argumentos. O programa acima compila sem erros, mas avisa quando
@SafeVarargs
anotação não é usada. Quando usamos
@SafeVarargs
anotação no exemplo acima, @SafeVarargs private void displayList(List<String>... lists) { ... }
Obtemos a mesma saída, mas sem nenhum aviso. Avisos desmarcados também são suprimidos quando usamos essa anotação.
5. @FunctionalInterface
O Java 8 introduziu pela primeira vez este
@FunctionalInterface
anotação. Esta anotação indica que a declaração de tipo na qual é usada é uma interface funcional. Uma interface funcional pode ter apenas um método abstrato. Exemplo 5:exemplo de anotação @FunctionalInterface
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
}
Se adicionarmos outro método abstrato, digamos
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
public void secondMethod(); // this throws compile error
}
Agora, quando executarmos o programa, receberemos o seguinte aviso:
Unexpected @FunctionalInterface annotation @FunctionalInterface ^ MyFuncInterface is not a functional interface multiple non-overriding abstract methods found in interface MyFuncInterface
Não é obrigatório usar
@FunctionalInterface
anotação. O compilador considerará qualquer interface que atenda à definição de interface funcional como uma interface funcional. Usamos essa anotação para garantir que a interface funcional tenha apenas um método abstrato.
No entanto, ele pode ter qualquer número de métodos padrão e estáticos porque eles têm uma implementação.
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
default void secondMethod() { ... }
default void thirdMethod() { ... }
}
Anotações personalizadas
Também é possível criar nossas próprias anotações personalizadas.
Sua sintaxe é:
[Access Specifier] @interface<AnnotationName> { DataType <Method Name>() [default value]; }
Aqui está o que você precisa saber sobre a anotação personalizada:
- As anotações podem ser criadas usando
@interface
seguido pelo nome da anotação. - A anotação pode ter elementos que parecem métodos, mas não têm uma implementação.
- O valor padrão é opcional. Os parâmetros não podem ter um valor nulo.
- O tipo de retorno do método pode ser primitivo, enum, string, nome de classe ou array desses tipos.
Exemplo 6:exemplo de anotação personalizada
@interface MyCustomAnnotation {
String value() default "default value";
}
class Main {
@MyCustomAnnotation(value = "programiz")
public void method1() {
System.out.println("Test method 1");
}
public static void main(String[] args) throws Exception {
Main obj = new Main();
obj.method1();
}
}
Saída
Test method 1
Meta Anotações
Meta-anotações são anotações que são aplicadas a outras anotações.
1. @Retenção
O
@Retention
anotação especifica o nível até o qual a anotação estará disponível. Sua sintaxe é:
@Retention(RetentionPolicy)
Existem 3 tipos de políticas de retenção:
- RetentionPolicy.SOURCE - A anotação está disponível apenas no nível de origem e é ignorada pelo compilador.
- RetentionPolicy.CLASS - A anotação está disponível para o compilador em tempo de compilação, mas é ignorada pela Java Virtual Machine (JVM).
- RetentionPolicy.RUNTIME - A anotação está disponível para a JVM.
Por exemplo,
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation{ ... }
2. @Documentado
Por padrão, as anotações personalizadas não estão incluídas na documentação oficial do Java. Para incluir nossa anotação na documentação Javadoc, usamos o
@Documented
anotação. Por exemplo,
@Documented
public @interface MyCustomAnnotation{ ... }
3. @Destino
Podemos restringir uma anotação a ser aplicada a destinos específicos usando o
@Target
anotação. Sua sintaxe é:
@Target(ElementType)
O
ElementType
pode ter um dos seguintes tipos:Tipo de elemento | Destino |
---|---|
ElementType.ANNOTATION_TYPE | Tipo de anotação |
ElementType.CONSTRUCTOR | Construtores |
ElementType.FIELD | Campos |
ElementType.LOCAL_VARIABLE | Variáveis locais |
ElementType.METHOD | Métodos |
ElementType.PACKAGE | Pacote |
ElementType.PARAMETER | Parâmetro |
ElementType.TYPE | Qualquer elemento da classe |
Por exemplo,
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation{ ... }
Neste exemplo, restringimos o uso desta anotação apenas para métodos.
Observação: Se o tipo de destino não for definido, a anotação poderá ser usada para qualquer elemento.
4. @Herdado
Por padrão, um tipo de anotação não pode ser herdado de uma superclasse. No entanto, se precisarmos herdar uma anotação de uma superclasse para uma subclasse, usamos o
@Inherited
anotação. Sua sintaxe é:
@Inherited
Por exemplo,
@Inherited
public @interface MyCustomAnnotation { ... }
@MyCustomAnnotation
public class ParentClass{ ... }
public class ChildClass extends ParentClass { ... }
5. @Repetível
Uma anotação que foi marcada por
@Repeatable
pode ser aplicado várias vezes à mesma declaração.
@Repeatable(Universities.class)
public @interface University {
String name();
}
O valor definido no
@Repeatable
anotação é a anotação do contêiner. A anotação do contêiner tem uma variável valor do tipo de matriz da anotação repetível acima. Aqui, Universities
são o tipo de anotação que contém.
public @interface Universities {
University[] value();
}
Agora, o
@University
A anotação pode ser usada várias vezes na mesma declaração.
@University(name = "TU")
@University(name = "KU")
private String uniName;
Se precisarmos recuperar os dados da anotação, podemos usar a API Reflection.
Para recuperar valores de anotação, usamos
getAnnotationsByType()
ou getAnnotations()
método definido na API de reflexão. Java