1. Overview
In this quick tutorial, we’ll have a look at the @SafeVarargs annotation.
2. The @SafeVarargs Annotation
Java 5 introduced the concept of varargs, or a method parameter of variable length, as well as parameterized types.
Combining these can cause problems for us:
public static <T> T[] unsafe(T... elements) {
return elements; // unsafe! don't ever return a parameterized varargs array
}
public static <T> T[] broken(T seed) {
T[] plant = unsafe(seed, seed, seed); // broken! This will be an Object[] no matter what T is
return plant;
}
public static void plant() {
String[] plants = broken("seed"); // ClassCastException
}
These problems are tricky for a compiler to confirm, and so it gives warnings whenever the two are combined, like in the case of unsafe:
warning: [unchecked] Possible heap pollution from parameterized vararg type T
public static <T> T[] unsafe(T... elements) {
This method, if used incorrectly, like in the case of broken, will pollute an Object[] array into the heap instead of the intended type b.
To squash this warning, we can add the @SafeVarargs annotation on final or static methods and constructors.
@SafeVarargs is like @SupressWarnings in that it allows us to declare that a particular compiler warning is a false positive. Once we ensure our actions are safe, we can add this annotation:
public class Machine<T> {
private List<T> versions = new ArrayList<>();
@SafeVarargs
public final void safe(T... toAdd) {
for (T version : toAdd) {
versions.add(version);
}
}
}
Safe use of varargs is a tricky concept in and of itself. For more information, Josh Bloch has a great explanation in his book, Effective Java.
3. Conclusion
In this quick article, we saw how to use the @SafeVarargs annotation in Java.
The full source code for the examples can be found over on GitHub.