A variable-arity parameter accepts a sequence of arguments through an array and must be the final parameter in the method declaration.
Java varargs: arrays at a method boundary
Java 8+. Use a JDK that supports this release.
The callee receives an array
A call can pass individual values or an existing compatible array. In the second case, the method receives the caller’s array reference. Mutating that array changes caller-visible state, so a read-only aggregation should avoid writes.
The shipment counter rejects negative counts and adds with checked arithmetic. That is a clearer failure contract than accepting a wrapped total. A zero-argument call produces an empty input and a total of zero.
A null array is not the same as an empty array. The explicit null check preserves the chosen error message. If the signature were Integer..., a null element could also fail during unboxing.
Keep overload resolution predictable
Varargs overloads mixed with ordinary overloads and boxed types can surprise readers. Prefer one clear entry point when the inputs have the same meaning. If two operations represent different policies, give them different names.
Generic varargs can expose a non-reifiable array and create heap-pollution hazards. Do not suppress warnings as a substitute for proving the method never writes unsafe values or exposes its array. See generic invariance.
Working program
public class ShipmentTotals {
static long total(int... shipmentCounts) {
if (shipmentCounts == null) {
throw new IllegalArgumentException("Counts cannot be null");
}
long total = 0;
for (int count : shipmentCounts) {
if (count < 0) throw new IllegalArgumentException("Negative count");
total = Math.addExact(total, count);
}
return total;
}
public static void main(String[] args) {
int[] counts = {7, 12, 4};
System.out.println(total(counts));
System.out.println(total());
}
}Output
23
0Cost and design choices
Summing n values requires O(n) time and O(1) additional working storage. A call with separate arguments may allocate an argument array. Passing an existing array avoids that new array, but it shares the reference.
When input arrives as a large stream, a varargs boundary requires materializing the batch. A streaming accumulator with an explicit reset and failure policy fits a different workload.
Common Mistakes
- Do not assume varargs copies an existing array.
- Do not pass null to mean no values.
- Do not hide generic-varargs warnings without understanding the array contract.
Connect the contracts
Compare the boundary explained in Method contracts with the assumptions made by this program.
Compare the boundary explained in Array sharing with the assumptions made by this program.
