Varargs
Variable-length Argument Lists in Java 5
Java 5 (and hence AspectJ 5) allows you to specify methods that take a
variable number of arguments of a specified type. This is achieved using
an ellipsis (...) in the method signature as shown:
A method or constructor may take at most one variable length argument, and
this must always be the last declared argument in the signature.
Calling Methods and Constructors with variable-length arguments
A varargs method may be called with zero or more arguments
in the variable argument position. For example, given the definition of
foo above, the following calls are all legal:
A varargs parameter is treated as an array within the
defining member. So in the body of foo we could write for example:
One consequence of this treatment of a varargs parameter as an array
is that you can also call a varargs method with an array:
Using Variable-length arguments in advice and pointcut expressions
AspectJ 5 allows variable-length arguments to be used for methods declared within
aspects, and for inter-type declared methods and constructors, in accordance with the rules
outlined in the previous section.
AspectJ 5 also allows variable length arguments to be matched by pointcut expressions and
bound as formals in advice.
Matching signatures based on variable length argument types
Recall from the definition of signature patterns given in the chapter on
annotations (), that MethodPattern
and ConstructorPattern are extended to allow a varargs
pattern in the last argument position of a method or constructor signature.
Method and constructor patterns are used in the call,
execution, initialization,
preinitialization, and withincode
pointcut designators. Some examples of usage follow:
call(* org.xyz.*.*(int, String...))
Matches a call join point for a call to a method defined in the
org.xyz package, taking an int
and a String vararg.
execution(* org.xyz.*.*(Integer...))
Matches an execution join point for the execution of a method defined in the
org.xyz package, taking an Integer vararg.
initialization(org.xyz.*.new((Foo || Goo)...))
Matches the initialization join point for the construction of an
object in the org.xyz package via a constructor
taking either a variable number of Foo parameters or
a variable number of Goo parameters. (This example
illustrating the use of a type pattern with ...).
A variable argument parameter and an array parameter are treated as distinct
signature elements, so given the method definitions:
The pointcut execution(* *.*(String...)) matches the execution join point
for foo, but not bar. The pointcut
execution(* *.*(String[])) matches the execution join point
for bar but not foo.
Exposing variable-length arguments as context in pointcuts and advice
When a varargs parameter is used within the body of a method, it has
an array type, as discussed in the introduction to this section. We follow the
same convention when binding a varargs parameter via the args
pointcut designator. Given a method
The call or execution join points for foo will be matched
by the pointcut args(int,String[]). It is not permitted
to use the varargs syntax within an args pointcut designator - so you
cannot write args(int,String...).
Binding of a varargs parameter in an advice statement is straightforward:
Since you cannot use the varargs syntax in the args
pointcut designator, you also cannot use the varargs syntax to declare
advice parameters.
Note: the proposal in this section does not allow you to
distinguish between a join point with a signature (int, String...)
and a join point with a signature (int, String[]) based
solely on the use of the args
pointcut designator. If this distinction is required, args
can always be coupled with call or
execution.