Java Varargs
In Java, method signatures are generally fixed. For example, a method that declares three parameters of a specific type must be called with those parameters. If we provide too many, too few, or incorrectly typed parameters, we will get a compile time error. Of course, we use method overloading to deal with the cases in which we need to declare a different number or different types of parameters.
However, every now and then it makes sense, or is more convenient; to have the one method handle any number of arguments that are thrown its way, just as we are allowed to do in languages like JavaScript (JS). The way many programmers previously simulated such behavior in Java was to create an array of parameters, then pass that array along as an argument to the specified method.
Since Java SE 5, with the introduction of Varargs (Variable number of arguments) concept, this rather messy approach is no longer necessary. Consider the following method signature:
public void testMethod(Object… args)
It is to be noted that there are three periods next to the parameter type. This is how we say the method that it is allowed to accept a variable number of arguments. The variable type must be Object, and it must be the last argument or only argument in the method signature. With this concept in mind, the following method calls are all completely legal:
testMethod(23, 34, 78);
testMethod("Hello", "Goodbye");
testMethod(123.75);
This is certainly meaningful, except for one thing. We have said that the arguments must be of type Object, yet we clearly pass along primitives in two of these calls. That means autoboxing is being applied – these arguments are passed along as Object types and the Java compiler manages the wrapping of primitive types on our behalf.
As we would expect, inside the method body, the parameters are handled as an array of type Object. The following code snippet shows how much code we may have needed to achieve the same thing prior to Java SE 5.
int num1 = 43;
int num2 = 67;
int num3 = 88;
Integer objNum1 = new Integer(num1);
Integer objNum2 = new Integer(num2);
Integer objNum3 = new Integer(num3);
Integer[] params = {objNum1, objNum1, objNum3}
testMethod(params);
Here, we have done all the primitive wrapping ourselves. Then, we have created the array-based parameter. Finally, we have to make the method call. So, that means we have saved a lot of work here.
An Example
The following program demonstrates the “Varargs concept” for students in a college with variable number of subjects. In the constructor of Student class, the last argument named Subject is using this Varargs concept (note the presence of triple dot … here). We are to calculate the total marks and the average marks obtained by each student. Note that every subject is having two parts: part1 and part2. We have displayed the result for individual student subject-wise. See the code below.
VarargsTest.java
class Subject {
String code, title;
int part1, part2, marks = 0;
public Subject(String code, String title, int part1, int part2) {
this.code = code;
this.title = title;
this.part1 = part1;
this.part2 = part2;
}
}
class Student {
int roll, total = 0, count=0;
String name, stream;
public Student(int roll, String name, String stream, Subject... sub) {
this.roll = roll;
this.name = name;
this.stream = stream;
for (Subject s : sub) {
s.marks = s.part1 + s.part2;
System.out.println("Code: " + s.code + "; Title: "
+ s.title + "; Marks: " + s.marks);
total += s.marks;
count++;
}
}
@Override
public String toString() {
double avg = (double)total/(double)count;
return "Roll: " + roll + "; Name: " + name + "; Stream: " + stream
+ "; Total: " + total+"; AVG: " + avg + "\n";
}
}
public class VarargsTest {
public static void main(String[] args) {
System.out.println("Display Information");
System.out.println("===================");
System.out.println("Student 1:~");
Student s1 = new Student(101, "Ram Sharma", "IT",
new Subject("CS301", "CO", 27, 52),
new Subject("CS302", "DS", 26, 50));
System.out.println(s1);
System.out.println("Student 2:~");
Student s2 = new Student(102, "Simran Paul", "CSE",
new Subject("CS301", "CO", 25, 45),
new Subject("CS302", "DS", 35, 55),
new Subject("CS303", "C++", 30, 50));
System.out.println(s2);
}
}
Output:
Display Information
===================
Student 1:~
Code: CS301; Title: CO; Marks: 79
Code: CS302; Title: DS; Marks: 76
Roll: 101; Name: Ram Sharma; Stream: IT; Total: 155; AVG: 77.5
Student 2:~
Code: CS301; Title: CO; Marks: 70
Code: CS302; Title: DS; Marks: 90
Code: CS303; Title: C++; Marks: 80
Roll: 102; Name: Simran Paul; Stream: CSE; Total: 240; AVG: 80.0