The @SafeVarargs Annotation
The marker annotation @SafeVarargs is used to instruct the compiler to suppress unchecked warnings that would otherwise be issued if the declaration or the invocation of a variable arity method or constructor has a variable arity parameter of a non-reifiable element type, as this can lead to heap pollution (§11.13, p. 630).
It is entirely the responsibility of the programmer to ensure that the variable arity method or constructor is well formed to prevent heap pollution before using the @SafeVarargs annotation to suppress the warnings. Note that the @SafeVarargs annotation suppresses any unchecked warnings both for the declaration and all call sites of the variable arity method or constructor.
In order to prevent heap pollution occurring in a subclass, a variable arity method cannot be overridden. The compiler will only allow this annotation on a method that is either static, private, or final. Constructors are not a problem in this regard as they cannot be overridden.
Example 25.3 below illustrates using the @SafeVarargs annotation. It is compiled with and without the @SafeVarargs annotation at (1). The output without the @Safe-Varargs annotation shows that two warnings are generated: the first one where the method printList() is declared at (2) and the second one at the call site for this method at (3). Since the variable arity method printList() is well formed, there is no risk in using the annotation.
Example 25.3 Using the @SafeVarargs Annotation
import java.util.ArrayList;
import java.util.List;
public class SafeVarargsTest{
@SafeVarargs // (1)
private static void printList(List<String>… toys) { // (2) List<String>[]
for (List<String> toy : toys) {
System.out.println(toy);
}
}
public static void main(String[] args) {
List<String> tList = new ArrayList<String>();
tList.add(“vaporizer”); tList.add(“slime gun”);
printList(tList); // (3) new List<String>[]
}
}
Without @SafeVarargs at (1):
>javac SafeVarargsTest.java
Note: SafeVarargsTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
>javac -Xlint:unchecked SafeVarargsTest.java
SafeVarargsTest.java:5: warning: [unchecked] Possible heap pollution from parame-
terized vararg type List<String>
private static void printList(List<String>… toys) { // (2) List<String>[]
^
SafeVarargsTest.java:14: warning: [unchecked] unchecked generic array creation for
varargs parameter of type List<String>[]
printList(tList); // (3) new List<String>[]
^
2 warnings
With @SafeVarargs:
>javac SafeVarargsTest.java
>java SafeVarargsTest
[vaporizer, slime gun]
The API of the SafeVarargs annotation type from the java.lang package is shown below:
@Documented
@Retention(RUNTIME)
@Target({CONSTRUCTOR,METHOD})
public @interface SafeVarargs
The primary use of the @SafeVarargs marker annotation is to suppress unchecked warnings alerting to potential heap pollution that can result from a variable arity parameter of a non-reifiable element type in a variable arity method or constructor.
The @SafeVarargs marker annotation has the RUNTIME retention policy and is thus not discarded by the compiler, making it possible to dynamically discover it through the use of the Reflection API. It can be used to annotate the declaration of a constructor or a method—the compiler ensures that the method is either static, private, or final. Its use will also be documented by the javadoc tool.
Table 25.3 provides a summary of selected standard annotations.
Table 25.3 Summary of Selected Standard Annotations
Standard annotation | Kind of annotation | Retention policy | Element type values of target | Compiler action |
@Override | Marker annotation | SOURCE | METHOD (which must be an instance or abstract method) | Error when criteria for overriding are not satisfied |
@FunctionalInterface | Marker annotation | RUNTIME | TYPE (which must be an interface) | Error when the interface does not have exactly one abstract method |
@Deprecated | Two elements: String since() default “”; boolean forRemoval() default false; | RUNTIME | CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE | Warnings when deprecated code is used or overridden in nondeprecated code |
@SuppressWarnings | Single-element annotation: String[] value(); | SOURCE | CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, MODULE, PARAMETER, TYPE | Warnings are suppressed |
@SafeVarargs | Marker annotation | RUNTIME | CONSTRUCTOR, METHOD ( which must be static, private , or final) | Error when no varargs parameter is specified or when applied to a method that is not either static, private, or final; otherwise warnings are suppressed |
Other Annotations
Many other annotations used in various contexts are defined in the language. Additional annotations may be provided with various extended APIs that are not part of the core Java language, but nevertheless are often used in practical programming, especially in server-side Java applications deployed in the Java Enterprise Edition or Micro Profile environments. Examples include the Java Persistence (JPA), Container Dependency Injection (CDI), and Bean Validation APIs. These APIs go beyond the Java SE Edition and are therefore not on the Java SE certification exam. However, they are essential for developing real-world Java applications.