123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- = Varargs
-
- [[varargs-inJava5]]
- == 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:
-
- [source, java]
- ....
- public void foo(int i, String... strings) {}
- ....
-
- 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:
-
- [source, java]
- ....
- foo(5);
- foo(5,"One String");
- foo(7,"One String","Two Strings");
- foo(3,"One String","Two Strings","Three Strings");
- ....
-
- A _varargs_ parameter is treated as an array within the defining member.
- So in the body of `foo` we could write for example:
-
- [source, java]
- ....
- public void foo(int i, String... strings) {
- String[] someStrings = strings;
- // rest of method body
- }
- ....
-
- One consequence of this treatment of a varargs parameter as an array is
- that you can also call a varargs method with an array:
-
- [source, java]
- ....
- foo(7,new String[] {"One String","Two Strings"});
- ....
-
- [[varargs-in-pcds]]
- == 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 (xref:annotations.adoc#signaturePatterns[Signature Patterns]), that `MethodPattern` and
- `ConstructorPattern` are extended to allow a `varargs` pattern in the
- last argument position of a method or constructor signature.
-
- [source, text]
- ....
- FormalsPattern :=
- '..' (',' FormalsPatternAfterDotDot)? |
- OptionalParensTypePattern (',' FormalsPattern)* |
- TypePattern '...'
-
- FormalsPatternAfterDotDot :=
- OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* |
- TypePattern '...'
- ....
-
- 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:
-
- [source, java]
- ....
- void foo(String...);
- void bar(String[]);
- ....
-
- 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
-
- [source, java]
- ....
- public void foo(int i, String... strings) {}
- ....
-
- 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:
-
- [source, java]
- ....
- before(int i, String[] ss) : call(* foo(int,String...)) && args(i,ss) {
- // varargs String... argument is accessible in advice body through ss
- // ...
- }
- ....
-
- 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`.
|