5.1 Creating a Variable-Length Argument List
Variable arguments allow you
to specify that a method can take multiple
arguments of the same type, and don't require that the number of arguments
be pre-determined (at compile- or runtime). This is one of the
integral parts of Tiger, in fact, as several of the new features of the language
actually incorporate varargs..
5.1.1 How do I do that?
First, get used to typing
the ellipsis (...). Those three little dots are the
key to varargs, and you'll be typing them quite often. Here's a version of
the Guitar constructor that uses varargs to allow for an indeterminate
number of String features:NOTEAll these constructors are shown, completed, in the source code for the com.oreilly.tiger.ch05.Guitar class.
The argument String... features indicates that any number of String
public Guitar(String builder, String model, String... features);
arguments may be supplied. So all of the following invocations are legal:
You could add the same variable-length argument to the other constructors:
Guitar guitar = new Guitar("Martin", "HD-28V",
"Hot-rodded by Dan Lashbrook", "Fossil Ivory Nut",
"Fossil Ivory Saddle", "Low-profile bridge pins");
Guitar guitar = new Guitar("Bourgeois", "OMC",
"Incredible flamed maple bindings on this one.");
Guitar guitar = new Guitar("Collings", "OM-42",
"Once owned by Steve Kaufman--one of a kind");
Example 5-1 shows a simple class that puts this all together, and even uses delegation to pass
public Guitar(String builder, String model,
GuitarWood backSidesWood, GuitarWood topWood,
float nutWidth, String... features)
public Guitar(String builder, String model,
GuitarWood backSidesWood, GuitarWood topWood,
float nutWidth,
GuitarInlay fretboardInlay, GuitarInlay topInlay,
String... features)
some varargs around.
Example 5-1. Using varargs in constructors
package com.oreilly.tiger.ch05;
public class Guitar {
private String builder;
private String model;
private float nutWidth;
private GuitarWood backSidesWood;
private GuitarWood topWood;
private GuitarInlay fretboardInlay;
private GuitarInlay topInlay;
private static final float DEFAULT_NUT_WIDTH = 1.6875f;
public Guitar(String builder, String model, String... features) {
this(builder, model, null, null, DEFAULT_NUT_WIDTH, null, null, features);
}
public Guitar(String builder, String model,
GuitarWood backSidesWood, GuitarWood topWood,
float nutWidth, String... features) {
this(builder, model, backSidesWood, topWood, nutWidth, null, null, features);
}
public Guitar(String builder, String model,
GuitarWood backSidesWood, GuitarWood topWood,
float nutWidth,
GuitarInlay fretboardInlay, GuitarInlay topInlay,
String... features) {
this.builder = builder;
this.model = model;
this.backSidesWood = backSidesWood;
this.topWood = topWood;
this.nutWidth = nutWidth;
this.fretboardInlay = fretboardInlay;
this.topInlay = topInlay;
}
}
5.1.2 What just happened?
When you specify a variable-length argument list, the Java compiler
essentially reads that as "create an array of type
<argument type>
". You typed:
NOTEYou'll get a compiler error from this, and one that's not all that descriptive
public Guitar(String builder, String model, String... features)
of the real problem.However, the compiler interprets this as:
This means that iteration over the argument list is simple (as shown in
public Guitar(String builder, String model, String[] features)
"Iterating Over Variable-Length Argument Lists"), as is any other programming
tasks you need to undertake. You can work with varargs just
as you would with arrays.However, there are some limitations. First, you can only use one ellipsis
per method. Thus, the following is illegal:
Additionally, the ellipsis must appear as the last argument to a method.
public Guitar(String builder, String model,
String... features, float... stringHeights)
5.1.3 What about...
...if you don't have any features to pass in? That's fine. Just call the constructor
in the old way:
Look closely, thoughthere is no constructor with the following signature:
Guitar guitar = new Guitar("Martin", "D-18");
So, what gives? Well, as an added bonus to varargs, not passing in an
public Guitar(String builder, String model)
argument is a legitimate option. So when you see String... features,
you should think "zero or more String arguments." That saves you from
creating another constructor without the varargs parameter.