| <html><head> | |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | |
| <title>Generics in AspectJ 5</title><link rel="stylesheet" href="aspectj-docs.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.44"><link rel="home" href="index.html" title="The AspectJTM 5 Development Kit Developer's Notebook"><link rel="up" href="generics.html" title="Chapter 3. Generics"><link rel="previous" href="generics.html" title="Chapter 3. Generics"><link rel="next" href="autoboxing.html" title="Chapter 4. Autoboxing and Unboxing"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Generics in AspectJ 5</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="generics.html">Prev</a> </td><th width="60%" align="center">Chapter 3. Generics</th><td width="20%" align="right"> <a accesskey="n" href="autoboxing.html">Next</a></td></tr></table><hr></div><div class="sect1"><a name="generics-inAspectJ5"></a><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="generics-inAspectJ5"></a>Generics in AspectJ 5</h2></div></div><p> | |
| AspectJ 5 provides full support for all of the Java 5 language features, including generics. Any legal Java 5 program is a | |
| legal AspectJ 5 progam. In addition, AspectJ 5 provides support for generic and parameterized types in pointcuts, inter-type | |
| declarations, and declare statements. Parameterized types may freely be used within aspect members, and support is | |
| also provided for generic <span class="emphasis"><i>abstract</i></span> aspects. | |
| </p><div class="sect2"><a name="matching-generic-and-parameterized-types-in-pointcut-expressions"></a><div class="titlepage"><div><h3 class="title"><a name="matching-generic-and-parameterized-types-in-pointcut-expressions"></a>Matching generic and parameterized types in pointcut expressions</h3></div></div><p> | |
| The simplest way to work with generic and parameterized types in pointcut expressions and type patterns | |
| is simply to use the raw type name. For example, the type pattern <tt>List</tt> will match | |
| the generic type <tt>List<E></tt> and any parameterization of that type | |
| (<tt>List<String>, List<?>, List<? extends Number></tt> and so on. This | |
| ensures that pointcuts written in existing code that is not generics-aware will continue to work as | |
| expected in AspectJ 5. It is also the recommended way to match against generic and parameterized types | |
| in AspectJ 5 unless you explicitly wish to narrow matches to certain parameterizations of a generic type. | |
| </p><p>Generic methods and constructors, and members defined in generic types, may use type variables | |
| as part of their signature. For example:</p><pre class="programlisting"> | |
| public class Utils { | |
| /** static generic method */ | |
| static <T> T first(List<T> ts) { ... } | |
| /** instance generic method */ | |
| <T extends Number> T max(T t1, T t2) { ... } | |
| } | |
| public class G<T> { | |
| // field with parameterized type | |
| T myData; | |
| // method with parameterized return type | |
| public List<T> getAllDataItems() {...} | |
| } | |
| </pre><p> | |
| AspectJ 5 does not allow the use of type variables in pointcut expressions and type patterns. Instead, members that | |
| use type parameters as part of their signature are matched by their <span class="emphasis"><i>erasure</i></span>. Java 5 defines the | |
| rules for determing the erasure of a type as follows. | |
| </p><p>Let <tt>|T|</tt> represent the erasure of some type <tt>T</tt>. Then:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>The erasure of a parameterized type <tt>T<T1,...,Tn></tt> is <tt>|T|</tt>. | |
| For example, the erasure of <tt>List<String></tt> is <tt>List</tt>.</td></tr><tr><td>The erasure of a nested type <tt>T.C</tt> is <tt>|T|.C</tt>. For example, | |
| the erasure of the nested type <tt>Foo<T>.Bar</tt> is <tt>Foo.Bar</tt>.</td></tr><tr><td>The erasure of an array type <tt>T[]</tt> is <tt>|T|[]</tt>. For example, | |
| the erasure of <tt>List<String>[]</tt> is <tt>List[]</tt>.</td></tr><tr><td>The erasure of a type variable is its leftmost bound. For example, the erasure of a | |
| type variable <tt>P</tt> is <tt>Object</tt>, and the erasure of a type | |
| variable <tt>N extends Number</tt> is <tt>Number</tt>.</td></tr><tr><td>The erasure of every other type is the type itself</td></tr></table><p>Applying these rules to the earlier examples, we find that the methods defined in <tt>Utils</tt> | |
| can be matched by a signature pattern matching <tt>static Object Utils.first(List)</tt> and | |
| <tt>Number Utils.max(Number, Number)</tt> respectively. The members of the generic type | |
| <tt>G</tt> can be matched by a signature pattern matching <tt>Object G.myData</tt> and | |
| <tt>public List G.getAllDataItems()</tt> respectively.</p><div class="sect3"><a name="d0e2195"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2195"></a>Restricting matching using parameterized types</h4></div></div><p>Pointcut matching can be further restricted to match only given parameterizations of parameter types (methods and constructors), return | |
| types (methods) and field types (fields). This is achieved by specifying a parameterized type pattern at the appropriate point | |
| in the signature pattern. For example, given the class <tt>Foo</tt>:</p><pre class="programlisting"> | |
| public class Foo { | |
| List<String> myStrings; | |
| List<Float> myFloats; | |
| public List<String> getStrings() { return myStrings; } | |
| public List<Float> getFloats() { return myFloats; } | |
| public void addStrings(List<String> evenMoreStrings) { | |
| myStrings.addAll(evenMoreStrings); | |
| } | |
| } | |
| </pre><p>Then a <tt>get</tt> join point for the field <tt>myStrings</tt> can be matched by the | |
| pointcut <tt>get(List Foo.myStrings)</tt> and by the pointcut <tt>get(List<String> Foo.myStrings)</tt>, | |
| but <span class="emphasis"><i>not</i></span> by the pointcut <tt>get(List<Number> *)</tt>.</p><p>A <tt>get</tt> join point for the field <tt>myFloats</tt> can be matched by the | |
| pointcut <tt>get(List Foo.myFloats)</tt>, the pointcut <tt>get(List<Float> *)</tt>, | |
| and the pointcut <tt>get(List<Number+> *)</tt>. This last example shows how AspectJ type | |
| patterns can be used to match type parameters types just like any other type. The pointcut | |
| <tt>get(List<Double> *)</tt> does <span class="emphasis"><i>not</i></span> match.</p><p>The execution of the methods <tt>getStrings</tt> and <tt>getFloats</tt> can be | |
| matched by the pointcut expression <tt>execution(List get*(..))</tt>, and the pointcut | |
| expression <tt>execution(List<*> get*(..))</tt>, but only <tt>getStrings</tt> | |
| is matched by <tt>execution(List<String> get*(..))</tt> and only <tt>getFloats</tt> | |
| is matched by <tt>execution(List<Number+> get*(..))</tt></p><p>A call to the method <tt>addStrings</tt> can be matched by the pointcut expression | |
| <tt>call(* addStrings(List))</tt> and by the expression <tt>call(* addStrings(List<String>))</tt>, | |
| but <span class="emphasis"><i>not</i></span> by the expression <tt>call(* addStrings(List<Number>))</tt>. | |
| </p><p>Remember that any type variable reference in a generic member is | |
| <span class="emphasis"><i>always</i></span> matched by its erasure. Thus given the following | |
| example:</p><pre class="programlisting"> | |
| class G<T> { | |
| List<T> foo(List<String> ls) { return null; } | |
| } | |
| </pre><p>The execution of <tt>foo</tt> can be matched by | |
| <tt>execution(List foo(List))</tt>, | |
| <tt>execution(List foo(List<String>>))</tt>, and | |
| <tt>execution(* foo(List<String<))</tt>but | |
| <span class="emphasis"><i>not</i></span> by <tt>execution(List<Object> foo(List<String>>)</tt> | |
| since the erasure of <tt>List<T></tt> is <tt>List</tt> | |
| and not <tt>List<Object></tt>. | |
| </p></div><div class="sect3"><a name="d0e2328"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2328"></a>Generic wildcards and signature matching</h4></div></div><p> | |
| When it comes to signature matching, a type parameterized using a generic wildcard is a distinct type. | |
| For example, <tt>List<?></tt> is a very different type to <tt>List<String></tt>, | |
| even though a variable of type <tt>List<String></tt> can be assigned to a variable of | |
| type <tt>List<?></tt>. Given the methods: | |
| </p><pre class="programlisting"> | |
| class C { | |
| public void foo(List<? extends Number> listOfSomeNumberType) {} | |
| public void bar(List<?> listOfSomeType) {} | |
| public void goo(List<Double> listOfDoubles) {} | |
| } | |
| </pre><div class="variablelist"><dl><dt><a name="d0e2349"></a><span class="term">execution(* C.*(List))</span></dt><dd><p><a name="d0e2352"></a>Matches an execution join point for any of the three methods. | |
| </p></dd><dt><a name="d0e2355"></a><span class="term">execution(* C.*(List<? extends Number>))</span></dt><dd><p><a name="d0e2358"></a>matches only the | |
| execution of <tt>foo</tt>, and <span class="emphasis"><i>not</i></span> the execution | |
| of <tt>goo</tt> since <tt>List<? extends Number></tt> and | |
| <tt>List<Double></tt> are distinct types. | |
| </p></dd><dt><a name="d0e2376"></a><span class="term">execution(* C.*(List<?>))</span></dt><dd><p><a name="d0e2379"></a>matches only the execution of <tt>bar</tt>. | |
| </p></dd><dt><a name="d0e2385"></a><span class="term">execution(* C.*(List<? extends Object+>))</span></dt><dd><p><a name="d0e2388"></a>matches both the execution of <tt>foo</tt> and the execution of <tt>bar</tt> | |
| since the upper bound of <tt>List<?></tt> is implicitly <tt>Object</tt>. | |
| </p></dd></dl></div></div><div class="sect3"><a name="d0e2403"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2403"></a>Treatment of bridge methods</h4></div></div><p>Under certain circumstances a Java 5 compiler is required to create <span class="emphasis"><i>bridge | |
| methods</i></span> that support the compilation of programs using raw types. Consider the types</p><pre class="programlisting"> | |
| class Generic<T> { | |
| public T foo(T someObject) { | |
| return someObject; | |
| } | |
| } | |
| class SubGeneric<N extends Number> extends Generic<N> { | |
| public N foo(N someNumber) { | |
| return someNumber; | |
| } | |
| } | |
| </pre><p>The class <tt>SubGeneric</tt> extends <tt>Generic</tt> | |
| and overrides the method <tt>foo</tt>. Since the upper bound of the type variable | |
| <tt>N</tt> in <tt>SubGeneric</tt> is different to the upper bound of | |
| the type variable <tt>T</tt> in <tt>Generic</tt>, the method <tt>foo</tt> | |
| in <tt>SubGeneric</tt> has a different erasure to the method <tt>foo</tt> | |
| in <tt>Generic</tt>. This is an example of a case where a Java 5 compiler will create | |
| a <span class="emphasis"><i>bridge method</i></span> in <tt>SubGeneric</tt>. Although you never see it, | |
| the bridge method will look something like this:</p><pre class="programlisting"> | |
| public Object foo(Object arg) { | |
| Number n = (Number) arg; // "bridge" to the signature defined in this type | |
| return foo(n); | |
| } | |
| </pre><p>Bridge methods are synthetic artefacts generated as a result of a particular compilation strategy and | |
| have no execution join points in AspectJ 5. So the pointcut <tt>execution(Object SubGeneric.foo(Object))</tt> | |
| does not match anything. (The pointcut <tt>execution(Object Generic.foo(Object))</tt> matches the | |
| execution of <tt>foo</tt> in both <tt>Generic</tt> and <tt>SubGeneric</tt> since | |
| both are implementations of <tt>Generic.foo</tt>). | |
| </p><p>It <span class="emphasis"><i>is</i></span> possible to <span class="emphasis"><i>call</i></span> a bridge method as the following short | |
| code snippet demonstrates. Such a call <span class="emphasis"><i>does</i></span> result in a call join point for the call to | |
| the method. | |
| </p><pre class="programlisting"> | |
| SubGeneric rawType = new SubGeneric(); | |
| rawType.foo("hi"); // call to bridge method (will result in a runtime failure in this case) | |
| Object n = new Integer(5); | |
| rawType.foo(n); // call to bridge method that would succeed at runtime | |
| </pre></div><div class="sect3"><a name="d0e2490"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2490"></a>Runtime type matching with this(), target() and args()</h4></div></div><p>The <tt>this()</tt>, <tt>target()</tt>, and | |
| <tt>args()</tt> pointcut expressions all match based on the runtime | |
| type of their arguments. Because Java 5 implements generics using erasure, it is not | |
| possible to ask at runtime whether an object is an instance of a given parameterization of a type | |
| (only whether or not it is an instance of the erasure of that parameterized type). Therefore | |
| AspectJ 5 does not support the use of parameterized types with the <tt>this()</tt> and | |
| <tt>target()</tt> pointcuts. Parameterized types may however be used in conjunction with | |
| <tt>args()</tt>. Consider the following class | |
| </p><pre class="programlisting"> | |
| public class C { | |
| public void foo(List<String> listOfStrings) {} | |
| public void bar(List<Double> listOfDoubles) {} | |
| public void goo(List<? extends Number> listOfSomeNumberType) {} | |
| } | |
| </pre><div class="variablelist"><dl><dt><a name="d0e2517"></a><span class="term">args(List)</span></dt><dd><p><a name="d0e2520"></a>will match an execution or call join point for any of | |
| these methods | |
| </p></dd><dt><a name="d0e2523"></a><span class="term">args(List<String>)</span></dt><dd><p><a name="d0e2526"></a>will match an execution | |
| or call join point for <tt>foo</tt>. | |
| </p></dd><dt><a name="d0e2532"></a><span class="term">args(List<Double>)</span></dt><dd><p><a name="d0e2535"></a>matches an execution or call join point for <tt>bar</tt>, and <span class="emphasis"><i>may</i></span> match | |
| at an execution or call join point for <tt>goo</tt> since it is legitimate to pass an | |
| object of type <tt>List<Double></tt> to a method expecting a <tt>List<? extends Number></tt>. | |
| </p><p> | |
| In this situation a runtime test would normally be applied to ascertain whether or not the argument | |
| was indeed an instance of the required type. However, in the case of parameterized types such a test is not | |
| possible and therefore AspectJ 5 considers this a match, but issues an <span class="emphasis"><i>unchecked</i></span> warning. | |
| For example, compiling the aspect <tt>A</tt> below with the class <tt>C</tt> produces the | |
| compilation warning: "unchecked match of List<Double> with List<? extends Number> when argument is | |
| an instance of List at join point method-execution(void C.goo(List<? extends Number>)) [Xlint:uncheckedArgument]"; | |
| </p></dd></dl></div><pre class="programlisting"> | |
| public aspect A { | |
| before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { | |
| for (Double d : listOfDoubles) { | |
| // do something | |
| } | |
| } | |
| } | |
| </pre><p>Like all Lint messages, the <tt>uncheckedArgument</tt> warning can be | |
| configured in severity from the default warning level to error or even ignore if preferred. | |
| In addition, AspectJ 5 offers the annotation <tt>@SuppressAjWarnings</tt> which is | |
| the AspectJ equivalent of Java's <tt>@SuppressWarnings</tt> annotation. If the | |
| advice is annotated with <tt>@SuppressWarnings</tt> then <span class="emphasis"><i>all</i></span> | |
| lint warnings issued during matching of pointcut associated with the advice will be | |
| suppressed. To suppress just an <tt>uncheckedArgument</tt> warning, use the | |
| annotation <tt>@SuppressWarnings("uncheckedArgument")</tt> as in the following | |
| examples: | |
| </p><pre class="programlisting"> | |
| import org.aspectj.lang.annotation.SuppressAjWarnings | |
| public aspect A { | |
| @SuppressAjWarnings // will not see *any* lint warnings for this advice | |
| before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { | |
| for (Double d : listOfDoubles) { | |
| // do something | |
| } | |
| } | |
| @SuppressAjWarnings("uncheckedArgument") // will not see *any* lint warnings for this advice | |
| before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { | |
| for (Double d : listOfDoubles) { | |
| // do something | |
| } | |
| } | |
| } | |
| </pre><p> | |
| The safest way to deal with <tt>uncheckedArgument</tt> warnings however is to restrict the pointcut | |
| to match only at those join points where the argument is guaranteed to match. This is achieved by combining | |
| <tt>args</tt> with a <tt>call</tt> or <tt>execution</tt> signature matching | |
| pointcut. In the following example the advice will match the execution of <tt>bar</tt> but not | |
| of <tt>goo</tt> since the signature of <tt>goo</tt> is not matched by the execution pointcut | |
| expression. | |
| </p><pre class="programlisting"> | |
| public aspect A { | |
| before(List<Double> listOfDoubles) : execution(* C.*(List<Double>)) && args(listOfDoubles) { | |
| for (Double d : listOfDoubles) { | |
| // do something | |
| } | |
| } | |
| } | |
| </pre><p>Generic wildcards can be used in args type patterns, and matching follows regular Java 5 assignability rules. For | |
| example, <tt>args(List<?>)</tt> will match a list argument of any type, and | |
| <tt>args(List<? extends Number>)</tt> will match an argument of type | |
| <tt>List<Number>, List<Double>, List<Float></tt> and so on. Where a match cannot be | |
| fully statically determined, the compiler will once more issue an <tt>uncheckedArgument</tt> warning. | |
| </p><p>Consider the following program:</p><pre class="programlisting"> | |
| public class C { | |
| public static void main(String[] args) { | |
| C c = new C(); | |
| List<String> ls = new ArrayList<String>(); | |
| List<Double> ld = new ArrayList<Double>(); | |
| c.foo("hi"); | |
| c.foo(ls); | |
| c.foo(ld); | |
| } | |
| public void foo(Object anObject) {} | |
| } | |
| aspect A { | |
| before(List<? extends Number> aListOfSomeNumberType) | |
| : call(* foo(..)) && args(aListOfSomeNumberType) { | |
| // process list... | |
| } | |
| } | |
| </pre><p>From the signature of <tt>foo</tt> all we know is that the runtime argument will be an instance of | |
| <tt>Object</tt>.Compiling this program gives the unchecked argument warning: | |
| "unchecked match of List<? extends Number> with List when argument is | |
| an instance of List at join point method-execution(void C.foo(Object)) [Xlint:uncheckedArgument]". | |
| The advice will not execute at the call join point for <tt>c.foo("hi")</tt> since <tt>String</tt> | |
| is not an instance of <tt>List</tt>. The advice <span class="emphasis"><i>will</i></span> execute at the call join points | |
| for <tt>c.foo(ls)</tt> and <tt>c.foo(ld)</tt> since in both cases the argument is an instance of | |
| <tt>List</tt>. | |
| </p><p>Combine a wildcard argument type with a signature pattern to avoid unchecked argument matches. In the example | |
| below we use the signature pattern <tt>List<Number+></tt> to match a call to any method taking | |
| a <tt>List<Number>, List<Double>, List<Float></tt> and so on. In addition the | |
| signature pattern <tt>List<? extends Number+></tt> can be used to match a call to a method | |
| declared to take a <tt>List<? extends Number></tt>, <tt>List<? extends Double></tt> | |
| and so on. Taken together, these restrict matching to only | |
| those join points at which the argument is guaranteed to be an instance of <tt>List<? extends Number></tt>.</p><pre class="programlisting"> | |
| aspect A { | |
| before(List<? extends Number> aListOfSomeNumberType) | |
| : (call(* foo(List<Number+>)) || call(* foo(List<? extends Number+>))) | |
| && args(aListOfSomeNumberType) { | |
| // process list... | |
| } | |
| } | |
| </pre></div><div class="sect3"><a name="d0e2686"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2686"></a>Binding return values in after returning advice</h4></div></div><p> | |
| After returning advice can be used to bind the return value from a matched join point. AspectJ 5 supports the use of | |
| a parameterized type in the returning clause, with matching following the same rules as described for args. For | |
| example, the following aspect matches the execution of any method returning a <tt>List</tt>, and makes | |
| the returned list available to the body of the advice. | |
| </p><pre class="programlisting"> | |
| public aspect A { | |
| pointcut executionOfAnyMethodReturningAList() : execution(List *(..)); | |
| after() returning(List<?> listOfSomeType) : executionOfAnyMethodReturningAList() { | |
| for (Object element : listOfSomeType) { | |
| // process element... | |
| } | |
| } | |
| } | |
| </pre><p>The pointcut uses the raw type pattern <tt>List</tt>, and hence it | |
| matches methods returning any kind of list (<tt>List<String>, List<Double></tt>, | |
| and so on). We've chosen to bind the returned list as the parameterized type | |
| <tt>List<?></tt> in the advice since Java's type checking will now ensure | |
| that we only perform safe operations on the list.</p><p>Given the class</p><pre class="programlisting"> | |
| public class C { | |
| public List<String> foo(List<String> listOfStrings) {...} | |
| public List<Double> bar(List<Double> listOfDoubles) {...} | |
| public List<? extends Number> goo(List<? extends Number> listOfSomeNumberType) {...} | |
| } | |
| </pre><p>The advice in the aspect below will run after the execution of <tt>bar</tt> | |
| and bind the return value. It will also run after the execution of <tt>goo</tt> and | |
| bind the return value, but gives an <tt>uncheckedArgument</tt> warning during | |
| compilation. It does <span class="emphasis"><i>not</i></span> run after the execution of <tt>foo</tt>. | |
| </p><pre class="programlisting"> | |
| public aspect Returning { | |
| after() returning(List<Double> listOfDoubles) : execution(* C.*(..)) { | |
| for(Double d : listOfDoubles) { | |
| // process double... | |
| } | |
| } | |
| } | |
| </pre><p>As with <tt>args</tt> you can guarantee that after returning advice only | |
| executes on lists <span class="emphasis"><i>statically determinable</i></span> to be of the right | |
| type by specifying a return type pattern in the associated pointcut. The | |
| <tt>@SuppressAjWarnings</tt> annotation can also be used if desired.</p></div><div class="sect3"><a name="d0e2742"></a><div class="titlepage"><div><h4 class="title"><a name="d0e2742"></a>Declaring pointcuts inside generic types</h4></div></div><p>Pointcuts can be declared in both classes and aspects. A pointcut declared in a generic | |
| type may use the type variables of the type in which it is declared. All references to | |
| a pointcut declared in a generic type from outside of that type must be via a parameterized type reference, | |
| and not a raw type reference.</p><p>Consider the generic type <tt>Generic</tt> with a pointcut <tt>foo</tt>: | |
| </p><pre class="programlisting"> | |
| public class Generic<T> { | |
| /** | |
| * matches the execution of any implementation of a method defined for T | |
| */ | |
| public pointcut foo() : execution(* T.*(..)); | |
| } | |
| </pre><p>Such a pointcut must be refered to using a parameterized reference as shown | |
| below.</p><pre class="programlisting"> | |
| public aspect A { | |
| // runs before the execution of any implementation of a method defined for MyClass | |
| before() : Generic<MyClass>.foo() { | |
| // ... | |
| } | |
| // runs before the execution of any implementation of a method defined for YourClass | |
| before() : Generic<YourClass>.foo() { | |
| // ... | |
| } | |
| // results in a compilation error - raw type reference | |
| before() : Generic.foo() { } | |
| } | |
| </pre></div></div><div class="sect2"><a name="inter-type-declarations"></a><div class="titlepage"><div><h3 class="title"><a name="inter-type-declarations"></a>Inter-type Declarations</h3></div></div><p> | |
| AspectJ 5 supports the inter-type declaration of generic methods, and of members on | |
| generic types. For generic methods, the syntax is exactly as for a regular method | |
| declaration, with the addition of the target type specification: | |
| </p><div class="variablelist"><dl><dt><a name="d0e2768"></a><span class="term"><T extends Number> T Utils.max(T first, T second) {...}</span></dt><dd><p><a name="d0e2771"></a>Declares a generic instance method <tt>max</tt> on the class <tt>Util</tt>. | |
| The <tt>max</tt> method takes two arguments, <tt>first</tt> and <tt>second</tt> which must | |
| both be of the same type (and that type must be Number or a subtype of Number) and returns an instance | |
| of that type. | |
| </p></dd><dt><a name="d0e2789"></a><span class="term">static <E> E Utils.first(List<E> elements) {...}</span></dt><dd><p><a name="d0e2792"></a>Declares a static generic method <tt>first</tt> on the class <tt>Util</tt>. | |
| The <tt>first</tt> method takes a list of elements of some type, and returns an instance | |
| of that type. | |
| </p></dd><dt><a name="d0e2804"></a><span class="term"><T> Sorter.new(List<T> elements,Comparator<? super T> comparator) {...}</span></dt><dd><p><a name="d0e2807"></a>Declares a constructor on the class <tt>Sorter</tt>. | |
| The constructor takes a list of elements of some type, and a comparator that can compare instances | |
| of the element type. | |
| </p></dd></dl></div><p> | |
| A generic type may be the target of an inter-type declaration, used either in its raw form or with | |
| type parameters specified. If type parameters are specified, then the number of type parameters given | |
| must match the number of type parameters in | |
| the generic type declaration. Type parameter <span class="emphasis"><i>names</i></span> do not have to match. | |
| For example, given the generic type <tt>Foo<T,S extends Number></tt> then: | |
| </p><div class="variablelist"><dl><dt><a name="d0e2822"></a><span class="term">String Foo.getName() {...}</span></dt><dd><p><a name="d0e2825"></a>Declares a <tt>getName</tt> method on behalf of the type <tt>Foo</tt>. It is | |
| not possible to refer to the type parameters of Foo in such a declaration. | |
| </p></dd><dt><a name="d0e2834"></a><span class="term">public R Foo<Q, R>.getMagnitude() {...}</span></dt><dd><p><a name="d0e2837"></a>Declares a method <tt>getMagnitude</tt> on the generic class <tt>Foo</tt>. | |
| The method returns an instance of the type substituted for the second type parameter in an invocation | |
| of <tt>Foo</tt> If <tt>Foo</tt> is declared as | |
| <tt>Foo<T,N extends Number> {...}</tt> then this inter-type declaration is | |
| equivalent to the declaration of a method <tt>public N getMagnitude()</tt> | |
| within the body of <tt>Foo</tt>. | |
| </p></dd><dt><a name="d0e2861"></a><span class="term">R Foo<Q, R extends Number>.getMagnitude() {...}</span></dt><dd><p><a name="d0e2864"></a>Results in a compilation error since a bounds specification is not allowed in this | |
| form of an inter-type declaration (the bounds are determined from the declaration of the | |
| target type). | |
| </p></dd></dl></div><p>A parameterized type may not be the target of an inter-type declaration. This is because | |
| there is only one type (the generic type) regardless of how many different invocations (parameterizations) of | |
| that generic type are made in a program. Therefore it does not make sense to try and declare a member | |
| on behalf of (say) <tt>Bar<String></tt>, you can only declare members on the generic | |
| type <tt>Bar<T></tt>. | |
| </p></div><div class="sect2"><a name="declare-parents"></a><div class="titlepage"><div><h3 class="title"><a name="declare-parents"></a>Declare Parents</h3></div></div><p>Both generic and parameterized types can be used as the parent type in a <tt>declare parents</tt> | |
| statement (as long as the resulting type hierarchy would be well-formed in accordance with Java's sub-typing | |
| rules). Generic types may also be used as the target type of a <tt>declare parents</tt> statement.</p><div class="variablelist"><dl><dt><a name="d0e2887"></a><span class="term">declare parents: Foo implements List<String></span></dt><dd><p><a name="d0e2890"></a>The <tt>Foo</tt> type implements the <tt>List<String></tt> interface. If | |
| <tt>Foo</tt> already implements some other parameterization of the <tt>List</tt> | |
| interface (for example, <tt>List<Integer></tt> then a compilation error will result since a | |
| type cannot implement multiple parameterizations of the same generic interface type. | |
| </p></dd></dl></div></div><div class="sect2"><a name="declare-soft"></a><div class="titlepage"><div><h3 class="title"><a name="declare-soft"></a>Declare Soft</h3></div></div><p>It is an error to use a generic or parameterized type as the softened exception type in a declare soft statement. Java 5 does | |
| not permit a generic class to be a direct or indirect subtype of <tt>Throwable</tt> (JLS 8.1.2).</p></div><div class="sect2"><a name="generic-aspects"></a><div class="titlepage"><div><h3 class="title"><a name="generic-aspects"></a>Generic Aspects</h3></div></div><p> | |
| AspectJ 5 allows an <span class="emphasis"><i>abstract</i></span> aspect to be declared as a generic type. Any concrete | |
| aspect extending a generic abstract aspect must extend a parameterized version of the abstract aspect. | |
| Wildcards are not permitted in this parameterization. | |
| </p><p>Given the aspect declaration:</p><pre class="programlisting"> | |
| public abstract aspect ParentChildRelationship<P,C> { | |
| ... | |
| } | |
| </pre><p>then</p><div class="variablelist"><dl><dt><a name="d0e2931"></a><span class="term">public aspect FilesInFolders extends ParentChildRelationship<Folder,File> {...</span></dt><dd><p><a name="d0e2934"></a>declares a concrete sub-aspect, <tt>FilesInFolders</tt> which extends the | |
| parameterized abstract aspect <tt>ParentChildRelationship<Folder,File></tt>. | |
| </p></dd><dt><a name="d0e2943"></a><span class="term">public aspect FilesInFolders extends ParentChildRelationship {...</span></dt><dd><p><a name="d0e2946"></a>results in a compilation error since the <tt>ParentChildRelationship</tt> aspect must | |
| be fully parameterized. | |
| </p></dd><dt><a name="d0e2952"></a><span class="term">public aspect ThingsInFolders<T> extends ParentChildRelationship<Folder,T></span></dt><dd><p><a name="d0e2955"></a>results in a compilation error since concrete aspects may not have type parameters. | |
| </p></dd><dt><a name="d0e2958"></a><span class="term">public abstract aspect ThingsInFolders<T> extends ParentChildRelationship<Folder,T></span></dt><dd><p><a name="d0e2961"></a>declares a sub-aspect of <tt>ParentChildRelationship</tt> in which <tt>Folder</tt> | |
| plays the role of parent (is bound to the type variable <tt>P</tt>). | |
| </p></dd></dl></div><p>The type parameter variables from a generic aspect declaration may be used in place of a type within any | |
| member of the aspect, <span class="emphasis"><i>except for within inter-type declarations</i></span>. | |
| For example, we can declare a <tt>ParentChildRelationship</tt> aspect to | |
| manage the bi-directional relationship between parent and child nodes as follows: | |
| </p><pre class="programlisting"> | |
| /** | |
| * a generic aspect, we've used descriptive role names for the type variables | |
| * (Parent and Child) but you could use anything of course | |
| */ | |
| public abstract aspect ParentChildRelationship<Parent,Child> { | |
| /** generic interface implemented by parents */ | |
| interface ParentHasChildren<C extends ChildHasParent>{ | |
| List<C> getChildren(); | |
| void addChild(C child); | |
| void removeChild(C child); | |
| } | |
| /** generic interface implemented by children */ | |
| interface ChildHasParent<P extends ParentHasChildren>{ | |
| P getParent(); | |
| void setParent(P parent); | |
| } | |
| /** ensure the parent type implements ParentHasChildren<child type> */ | |
| declare parents: Parent implements ParentHasChildren<Child>; | |
| /** ensure the child type implements ChildHasParent<parent type> */ | |
| declare parents: Child implements ChildHasParent<Parent>; | |
| // Inter-type declarations made on the *generic* interface types to provide | |
| // default implementations. | |
| /** list of children maintained by parent */ | |
| private List<C> ParentHasChildren<C>.children = new ArrayList<C>(); | |
| /** reference to parent maintained by child */ | |
| private P ChildHasParent<P>.parent; | |
| /** Default implementation of getChildren for the generic type ParentHasChildren */ | |
| public List<C> ParentHasChildren<C>.getChildren() { | |
| return Collections.unmodifiableList(children); | |
| } | |
| /** Default implementation of getParent for the generic type ChildHasParent */ | |
| public P ChildHasParent<P>.getParent() { | |
| return parent; | |
| } | |
| /** | |
| * Default implementation of addChild, ensures that parent of child is | |
| * also updated. | |
| */ | |
| public void ParentHasChildren<C>.addChild(C child) { | |
| if (child.parent != null) { | |
| child.parent.removeChild(child); | |
| } | |
| children.add(child); | |
| child.parent = this; | |
| } | |
| /** | |
| * Default implementation of removeChild, ensures that parent of | |
| * child is also updated. | |
| */ | |
| public void ParentHasChildren<C>.removeChild(C child) { | |
| if (children.remove(child)) { | |
| child.parent = null; | |
| } | |
| } | |
| /** | |
| * Default implementation of setParent for the generic type ChildHasParent. | |
| * Ensures that this child is added to the children of the parent too. | |
| */ | |
| public void ChildHasParent<P>.setParent(P parent) { | |
| parent.addChild(this); | |
| } | |
| /** | |
| * Matches at an addChild join point for the parent type P and child type C | |
| */ | |
| public pointcut addingChild(Parent p, Child c) : | |
| execution(* ParentHasChildren.addChild(ChildHasParent)) && this(p) && args(c); | |
| /** | |
| * Matches at a removeChild join point for the parent type P and child type C | |
| */ | |
| public pointcut removingChild(Parent p, Child c) : | |
| execution(* ParentHasChildren.removeChild(ChildHasParent)) && this(p) && args(c); | |
| } | |
| </pre><p> | |
| The example aspect captures the protocol for managing a bi-directional parent-child relationship between | |
| any two types playing the role of parent and child. In a compiler implementation managing an abstract syntax | |
| tree (AST) in which AST nodes may contain other AST nodes we could declare the concrete aspect: | |
| </p><pre class="programlisting"> | |
| public aspect ASTNodeContainment extends ParentChildRelationship<ASTNode,ASTNode> { | |
| before(ASTNode parent, ASTNode child) : addingChild(parent, child) { | |
| ... | |
| } | |
| } | |
| </pre><p> | |
| As a result of this declaration, <tt>ASTNode</tt> gains members: | |
| </p><table class="simplelist" border="0" summary="Simple list"><tr><td><tt>List<ASTNode> children</tt></td></tr><tr><td><tt>ASTNode parent</tt></td></tr><tr><td><tt>List<ASTNode>getChildren()</tt></td></tr><tr><td><tt>ASTNode getParent()</tt></td></tr><tr><td><tt>void addChild(ASTNode child)</tt></td></tr><tr><td><tt>void removeChild(ASTNode child)</tt></td></tr><tr><td><tt>void setParent(ASTNode parent)</tt></td></tr></table><p> | |
| In a system managing orders, we could declare the concrete aspect: | |
| </p><pre class="programlisting"> | |
| public aspect OrderItemsInOrders extends ParentChildRelationship<Order,OrderItem> { | |
| } | |
| </pre><p> | |
| As a result of this declaration, <tt>Order</tt> gains members: | |
| </p><table class="simplelist" border="0" summary="Simple list"><tr><td><tt>List<OrderItem> children</tt></td></tr><tr><td><tt>List<OrderItem> getChildren()</tt></td></tr><tr><td><tt>void addChild(OrderItem child)</tt></td></tr><tr><td><tt>void removeChild(OrderItem child)</tt></td></tr></table><p>and <tt>OrderItem</tt> gains members:</p><table class="simplelist" border="0" summary="Simple list"><tr><td><tt>Order parent</tt></td></tr><tr><td><tt>Order getParent()</tt></td></tr><tr><td><tt>void setParent(Order parent)</tt></td></tr></table><p>A second example of an abstract aspect, this time for handling exceptions in a uniform | |
| manner, is shown below:</p><pre class="programlisting"> | |
| abstract aspect ExceptionHandling<T extends Throwable> { | |
| /** | |
| * method to be implemented by sub-aspects to handle thrown exceptions | |
| */ | |
| protected abstract void onException(T anException); | |
| /** | |
| * to be defined by sub-aspects to specify the scope of exception handling | |
| */ | |
| protected abstract pointcut inExceptionHandlingScope(); | |
| /** | |
| * soften T within the scope of the aspect | |
| */ | |
| declare soft: T : inExceptionHandlingScope(); | |
| /** | |
| * bind an exception thrown in scope and pass it to the handler | |
| */ | |
| after() throwing (T anException) : inExceptionHandlingScope() { | |
| onException(anException); | |
| } | |
| } | |
| </pre><p>Notice how the type variable <tt>T extends Throwable</tt> allows the | |
| components of the aspect to be designed to work together in a type-safe manner. The | |
| following concrete sub-aspect shows how the abstract aspect might be extended to | |
| handle <tt>IOExceptions</tt>.</p><pre class="programlisting"> | |
| public aspect IOExceptionHandling extends ExceptionHandling<IOException>{ | |
| protected pointcut inExceptionHandlingScope() : | |
| call(* doIO*(..)) && within(org.xyz..*); | |
| /** | |
| * called whenever an IOException is thrown in scope. | |
| */ | |
| protected void onException(IOException ex) { | |
| System.err.println("handled exception: " + ex.getMessage()); | |
| throw new MyDomainException(ex); | |
| } | |
| } | |
| </pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="generics.html">Prev</a> </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right"> <a accesskey="n" href="autoboxing.html">Next</a></td></tr><tr><td width="40%" align="left">Chapter 3. Generics </td><td width="20%" align="center"><a accesskey="u" href="generics.html">Up</a></td><td width="40%" align="right"> Chapter 4. Autoboxing and Unboxing</td></tr></table></div></body></html> |