J2SE 1.5 provides a "Varargs" mechanism. With this mechanism, you can define formal parameters that can match multiple arguments. Thus, it is possible to pass a variable number of arguments in a simpler way. This article describes how this mechanism is used, and how it interacts with arrays, generics, and overloads.
by J2SE 1.4, it was not possible to define a variable number of arguments in a Java program-because Java requires both the number and type of arguments (Arguments) and formal parameters (Parameters) to match each other, and the number of formal parameters is fixed when the method is defined. Although it is possible to provide a version with a different number of parameters for the same method by overloading the mechanism, this still does not achieve the purpose of arbitrarily changing the number of arguments.
However, the semantics of some methods require that they be able to accept a variable number of arguments-such as the well-known main method, which requires that all command-line arguments be accepted as arguments, and that the number of command-line arguments cannot be determined at all beforehand.
Traditionally, the use of an array to wrap the arguments to be passed is generally used to cope with this problem.
1. Wrap an argument with an array
The "Wrap arguments with an array" approach can be divided into three steps: First, define an array-type parameter for this method, and then, when called, generate an array that contains all the arguments to pass, and finally, pass the array as an argument in the past.
This approach can effectively achieve the "let the method can accept the variable number of parameters" purpose, but the invocation of the form is not simple enough.
The varargs mechanism is provided in J2SE 1.5, allowing direct definition of formal parameters that can match multiple arguments. Thus, it is possible to pass a variable number of arguments in a simpler way.
The meaning of varargs
Generally speaking, "Varargs" is the meaning of "variable number of arguments". It is sometimes referred to simply as "variable arguments", but because it does not indicate what is mutable, the meaning is somewhat blurred.
2. How to define the variable number of arguments
Simply add three consecutive "." Between "type" and "parameter name" of a formal parameter. (That is, "...", an ellipsis in an English sentence), it can be matched to an indeterminate argument. A method with such a parameter is a variable number of arguments.
Listing 1: Method of variable number of arguments private static int sumup (int ... values) {
}
Note that only the last formal parameter can be defined as "can and does not have an argument to match". Therefore, there can be only one such parameter in a method. Also, if the method has other parameters, put them in the front position.
The compiler converts the last parameter into an array parameter behind the box and makes a tick in the compiled class file, indicating that this is a variable number of arguments.
Listing 2: Secret form of method with variable number of arguments private static int sumup (int[] values) {
}
Because of this transformation, it is no longer possible to define a method that is consistent with the converted method signature for this class.
Listing 3: Combined private static int sumup (int ... values) that causes compilation errors {
}
private static int SumUp (int[] values) {
} The question of the survival of blanks
According to the syntax of J2SE 1.5, whitespace characters in front of "..." are optional. This will be preceded by "..." by adding white space characters (shaped like "object ... args") and not preceded by "..." with whitespace characters (shaped like "object ... args") in two ways. Because the Java Code Conventions, currently in conjunction with J2SE 1.5, is not officially released, it is not possible to know which one is more orthodox. However, considering that the array parameters also have "Object [] args" and "object[" args "two ways of writing, and the orthodox notation is not" [] "before the addition of white space characters, it seems to take a blank" object ... args "In the overall way more coordinated.
3. How to invoke a variable number of arguments
You can call a method with a variable number of arguments, as long as you write the arguments you want to pass to a corresponding location. No additional steps are required.
Listing 4: Several arguments can be passed SumUp (1, 3, 5, 7);
Secretly, the compiler translates this invocation process into the form of "array wrap arguments":
Listing 5: A sneak array created SumUp (new Int[]{1, 2, 3, 4});
Also, there are 0 of "unsure", so the call is reasonable:
Listing 6:0 Arguments can also be passed sumup ();
This method of invocation is the result of the compiler's secret conversion, which is equivalent to this:
Listing 7: The 0 argument corresponds to an empty array sumup (new int[] {});
Note that passing in the past is an empty array, not NULL. This can be done in a uniform form, without having to detect exactly which case it belongs to.
4. Handle a variable number of arguments
The method of dealing with a variable number of arguments is basically the same as the method for working with array arguments. All arguments are saved to an array with the same name as the parameter. According to the actual needs, the elements in this array read out, to be steamed to boil, you can be arbitrary.
Listing 8: Handling the received arguments private static int sumup (int ... Values) {
int sum = 0;
for (int i = 0; i < values.length; i++) {
Sum + = Values[i];
}
return sum;
} 5. Forward a variable number of arguments
Sometimes, after you accept a set of variable arguments, you pass them to another method with a variable number of arguments. Because there is no way to know the number of accepted sets of arguments in the code, it is not feasible to "write them down to where they appear". However, this does not mean that this is an unfinished task because there is another way to invoke a variable number of arguments.
In the eyes of the compiler for J2SE 1.5, the variable number of arguments is a special case of the method with the last array parameter. Therefore, the entire set of arguments to be passed is placed in an array beforehand, and the array is passed as the last argument to a variable number of arguments, without causing any errors. With this feature, the forwarding can be completed smoothly.
Listing 9: Forwarding the received arguments public class Printfsample {
public static void Main (string[] args) {
Print out "pi:3.141593 e:2.718282"
PrintOut ("Pi:%f e:%f/n", Math.PI, MATH.E);
}
private static void PrintOut (String format, Object ... args) {
J2SE 1.5 printstream new printf (String format, Object ... args) method
System.out.printf (format, args);
}
} "printf" and "sprintf" in Java
printf in C (output strings in a certain format) and sprintf (combining strings in a certain format) are classic examples of using the varargs mechanism. Similar functionality is provided in J2SE 1.5, respectively, in the Java.io.PrintStream class and the Java.lang.String class.
The ability to output strings in a certain format can be achieved by calling the PrintStream object's printf (string format, Object ... args) method.
To combine the work of a string in a certain format, you can do this by calling the string format (string format, Object ... args) static method.
6. Is it an array? Not an array?
Although secretly, the compiler converts a parameter that can match an indeterminate argument to an array parameter, and it can also be passed to a variable number of arguments by using a list of arguments, but this does not mean that there is no difference between a parameter that can match an indeterminate argument and an array parameter.
One obvious difference is that if you call a method that is the array parameter in the form of a variable number of arguments to invoke, only a compilation error of "cannot be applied" is caused.
Listing 10: A compilation error for "Cannot is applied to" private static void Testoverloading (int[] i) {
System.out.println ("A");
}
public static void Main (string[] args) {
Testoverloading (1, 2, 3);//Compilation error
}
For this reason, you cannot directly use this concise invocation method when calling a method that only supports the use of an array to wrap arguments (for example, those left behind in a third-party class library that is not specifically designed for J2SE 1.5).
If you cannot modify the original class and add a variable number of arguments to the method you want to invoke, and you want to use this concise invocation, you can introduce a local extension with the introduction of an additional function (introduce Foreign method) and Extension) "to approximate the purpose of the reconstruction technique.
7. When a variable number of arguments encounters a generic
A "generic" mechanism has been added to J2SE 1.5 to parameterize a type under certain conditions. For example, when writing a class, the type of the formal parameter of a method is represented by an identifier (such as T), and when the identifier exactly represents what type it is, it is specified when the instance of the class is generated. This mechanism can be used to provide more full code reuse and stricter compile-time type checking.
However, a generic mechanism cannot be used with a variable number of parameters. If the type of a formal parameter that matches an indeterminate argument is represented by an identifier, the compiler will give a "Generic array creation" error.
Listing 11: When VarArgs encounters a generic private static <T> void Testvarargs (T ... args) {//Compile error
}
This behavior is caused by an intrinsic constraint on the generic mechanism in J2SE 1.5--You cannot create an instance of this type with the type represented by the identifier. There is basically no good solution to this problem until there is a Java version that supports this constraint.
However, the traditional "wrap with arrays" approach is not constrained by this constraint.
Listing 12: Workarounds that can be compiled private static <T> void Testvarargs (t[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println (Args[i]);
}
} 8. Selection problems in overloading
Java supports the "overloaded" mechanism, which allows for a number of different methods that have only formal parameter lists in the same class. The compiler then chooses which method to execute based on the arguments that are called.
The traditional choice is basically based on the principle of "special preference". The special degree of a method depends on the number of conditions that need to be met in order for it to run smoothly, and the more specific the requirement is.
After the introduction of the varargs mechanism, this principle still applies, but the issues to be considered are enriched-traditionally, in the various versions of an overloaded method, only those with the same number of formal parameters as the number of actual parameters have been further considered. However, after the introduction of the varargs mechanism, it is possible to have two versions that can match, in other respects also indistinguishable, only a fixed number of arguments, and a variable number of arguments.
When this happens, the decision rule is "a version with a fixed number of arguments takes precedence over a variable number of arguments."
Listing 13: A fixed version of the number of arguments priority public class Overloadingsamplea {
public static void Main (string[] args) {
Testoverloading (1);//Print out a
Testoverloading (1, 2);//Print out B
Testoverloading (1, 2, 3);//Print out C
}
private static void testoverloading (int i) {
System.out.println ("A");
}
private static void testoverloading (int i, int j) {
System.out.println ("B");
}
private static void testoverloading (int i, int ... more) {
System.out.println ("C");
}
}
If, in the compiler's view, more than one method has the same priority, it will fall into a state where it is impossible to make a selection of which method to invoke. At this time, it will produce a "reference to be called method name is ambiguous" compile error, and patiently wait for some changes, enough to exempt it from the confusion of the arrival of the source code.
After the introduction of the varargs mechanism, this could lead to confusion and a number of additional cases. For example, there may be two versions that can match, and in other respects, they are conflicting occurrences with variable number of arguments.
Listing 14: No, it's embarrassing. Compiler public class Overloadingsampleb {
public static void Main (string[] args) {
Testoverloading (1, 2, 3);//Compilation error
}
private static void Testoverloading (Object ... args) {
}
private static void Testoverloading (Object o, Object ... args) {
}
}
In addition, because there is a "autoboxing/auto-unboxing" mechanism in J2SE 1.5, it is possible that two versions can be matched, and the number of arguments is variable, and the other is exactly the same, except that an acceptable argument is a basic type. Another acceptable argument is the collision of the parcel class.
New issues brought by listing 15:autoboxing/auto-unboxing public class Overloadingsamplec {
public static void Main (string[] args) {
/* Compilation Error */
Testoverloading (1, 2);
/* or compile Error */
Testoverloading (New Integer (1), new Integer (2));
}
private static void testoverloading (int ... args) {
}
private static void Testoverloading (Integer ... args) {
}
} 9. Inductive summary
Compared with the "wrap with arrays" approach, the method of changing the number of real arguments is simpler and more clear when the arguments are passed on the call. However, this mechanism also has its own limitations, not a perfect solution.
Java uses ellipses instead of multiple parameters (parameter types ...). Name of the parameter)