Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

A variable arity (aka varargs) method is a method that can take a variable number of arguments. The method must contain at least one fixed argument. When processing a variable arity method call, the Java compiler checks the types of all arguments, and all of the variable actual arguments must match the variable formal argument type. However, compile-time type checking is ineffective when Object or generic parameter types are used [Bloch 2008]. The presence of initial parameters of specific types is irrelevant; the compiler will remain unable to check Object or generic variable parameter types. Enable strong compile-time type checking of variable arity methods by using the most specific type possible for the method parameter.

Noncompliant Code Example (Object)

This noncompliant code example sums a set of numbers using a variable arity method that uses Object as the variable arity type. Consequently, this method accepts an arbitrary mix of parameters of any object type. Legitimate uses of such declarations are rare (but see the "Applicability" section of this guideline).

Code Block
bgColor#FFCCCC
double sum(Object... args) {
   double result = 0.0;
   for (Object arg : args) {
     if (arg instanceof Byte) {
       result += ((Byte) arg).byteValue();
     } else if (arg instanceof Short) {
       result += ((Short) arg).shortValue();
     } else if (arg instanceof Integer) {
       result += ((Integer) arg).intValue();
     } else if (arg instanceof Long) {
       result += ((Long) arg).longValue();
     } else if (arg instanceof Float) {
       result += ((Float) arg).floatValue();
     } else if (arg instanceof Double) {
       result += ((Double) arg).doubleValue();
     } else {
       throw new ClassCastException();
     }
   }
   return result;
}

Compliant Solution (Number)

This compliant solution defines the same method but uses the Number type. This abstract class is general enough to encompass all numeric types, yet specific enough to exclude nonnumeric types.

Code Block
bgColor#ccccff
double sum(Number... args) {
  // ...
}

Noncompliant Code Example (Generic Type)

This noncompliant code example declares the same variable arity method using a generic type parameter. It

Wiki Markup
The Java compiler type-checks the arguments to a varargs method to ensure that they are of the same type or object reference. However, the compile-time checking is ineffective when two method signatures are used in particular—{{Object}} and the generic type {{T}} \[[Bloch 2008|AA. Bibliography#Bloch 08]\]. Another requirement for providing strong compile-time type checking of variable argument methods is to be as specific as possible when declaring the type of the method parameter.

Noncompliant Code Example

This noncompliant code example declares two varargs methods. As written, the first accepts an arbitrary mix of parameters of any object type; the second accepts a variable number of parameters that are all of the same object type. Although such declarations have legitimate uses (see exception below), those uses rarely arise; avoid use of such declarations in general; however, it may be any object type. Again, legitimate uses of such declarations are rare.

Code Block
bgColor#FFCCCC

ReturnType1 suspect1(Object<T> double sum(T... args) {
 }
<T> ReturnType2// suspect2(T... args) { }

}

Compliant Solution

...

(Generic Type)

This compliant solution defines the same generic method using the Number typeBe as specific as possible when declaring parameter types; avoid Object and imprecise generic types in varargs.

Code Block
bgColor#ccccff

ReturnType1 specific1(somePrimitiveType1<T extends Number> double sum(T... args) {
 } // int, or whatever
ReturnType2 specific2(SpecificObjectType2... args) { }

}

Be as specific as possible when declaring parameter types; avoid Object and imprecise generic types in variable arity methods. Retrofitting old methods containing final array parameters with generically typed variable arity parameters is not always a good idea. For example, given a method that does not accept an argument of a particular type, it could be possible to override the compile-time checking—through the use of generic variable arity parameters—so that the method would compile cleanly rather than correctly, causing a runtime error [Bloch 2008]. Wiki MarkupRetrofitting old methods containing final array parameters with generically-typed varargs is not always a good idea. This is because, if some method did not accept an argument of a particular type, it could be possible to override the compile-time checking so that, with the use of generic varargs, it now compiles cleanly \[[Bloch 2008|AA. Bibliography#Bloch 08]\].

Also, note that autoboxing does not allow prevents strong compile-time type checking of primitive types and their corresponding wrapper classes.

Exceptions

For instance, this compliant solution produces the following warning but works as expected:

Java.java:10: warning: [unchecked] Possible heap pollution from parameterized vararg type T
<T extends Number> double sum(T... args) {

Applicability

Injudicious use of variable arity parameter types prevents strong compile-time type checking, creates ambiguity, and diminishes code readability.

Variable arity DCL09-EX1: Varargs signatures using Object and imprecise generic types are acceptable when, and only when , the body of the method uses no casts or auto-boxing, and lacks both casts and autoboxing and it also compiles without error. Consider the following example, which operates correctly for all object types and type-checks successfully:

Code Block
bgColor#ccccff
<T> 
Collection<T> assembleCollection(T... args) {
  Collection<T> result =return new HashSet<T>(Arrays.asList();
  // add each argument to the result collection
  return result args));
}

operates correctly for all object types and type-checks successfully.

Risk Assessment

Unmindful use of the varargs feature breaks strong compile-time type checking, creates ambiguity, and diminishes code readability.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

DCL09-J

low

unlikely

medium

P2

L3

Automated Detection

Automated detection appears to be straightforward.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Bibliography

Wiki Markup
\[[Bloch 2008|AA. Bibliography#Bloch 08]\] Item 42: "Use varargs judiciously"
\[[Steinberg 2005|AA. Bibliography#Steinberg 05]\] "Using the Varargs Language Feature"
\[[Sun 2006|AA. Bibliography#Sun 06]\] [varargs|http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html] 

In some circumstances, it is necessary to use a variable arity parameter of type Object.  A good example is the method java.util.Formatter.format(String format, Object... args), which can format objects of any type.

Automated detection is straightforward.

Bibliography

[Bloch 2008]

Item 42, "Use Varargs Judiciously"

[Steinberg 2008]

"Using the Varargs Language Feature"

[Oracle 2011b]

Varargs

 

...

Image Added Image Added Image AddedDCL08-J. Avoid overloading varargs methods      03. Declarations and Initialization (DCL)      DCL10-J. Ensure proper initialization by declaring class and instance variables final