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

Click here to view code image

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):

Click here to view code image

>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:

Click here to view code image

>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 annotationKind of annotationRetention policyElement type values of targetCompiler action
@OverrideMarker annotationSOURCEMETHOD (which must be an instance or abstract method)Error when criteria for overriding are not satisfied
@FunctionalInterfaceMarker annotationRUNTIMETYPE (which must be an interface)Error when the interface does not have exactly one abstract method
@DeprecatedTwo elements: String since()
default “”;
boolean
forRemoval()
default false;

RUNTIMECONSTRUCTOR,
FIELD,
LOCAL_VARIABLE,
METHOD, PACKAGE,
MODULE,
PARAMETER, TYPE

Warnings when deprecated code is used or overridden in nondeprecated code
@SuppressWarningsSingle-element annotation: String[]
value();

SOURCECONSTRUCTOR,
FIELD,
LOCAL_VARIABLE,
METHOD, MODULE,
PARAMETER, TYPE

Warnings are suppressed
@SafeVarargsMarker annotationRUNTIMECONSTRUCTOR,
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.

Leave a Reply

Your email address will not be published. Required fields are marked *