Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Understanding generic types in args(..) construction

Hi Fernando.

I think the confusion here arises from a misunderstanding of the
subtyping relationship with generics on your part.

ArrayList<X> is always a subtype of List<X> for some concrete type X,
and therefore a match is generally possible and AspectJ determines
whether or not to match using a runtime check.

*However* no List<Y> is ever subtype of a List<X> for any two
different concrete types X and Y, regardless of whether Y is a subtype
of X! As a consequence, also List<Integer> cannot possibly be an
ArrayList<Number>.

What surprises me is the fact that the first advice in BC matches.
Actually this should not match either, I believe, because also a
List<Integer> can never be a List<Number>. I am not sure... could this
have to do with type erasure?

Eric

2008/11/1 Fernando Rubbo <fernando.rubbo@xxxxxxxxx>:
> Hi all,
>
> I have a question about args(..) and after(..) returning(..) construction
> semantics when generic types are applied.
> Actually, it is not clear for me how it is working and why it is working
> this way. Let me show an example to help to depict my thoughts.
>
> class C{
>     void m(List<Integer> e){}
> }
>
> aspect AC {
>     void around():execution(* C.*(..)) && args(List<Integer>) {} // Matchs
> C.m
>     void around():execution(* C.*(..)) && args(ArrayList<Integer>) {} //
> Unchecked match C.m - uses rRuntime check
> }
>
> In this simple example, it is easy to notice that both advices will match
> the method C.m. Note that the second one will make a runtime test to check
> if the method caller has passed, as a parameter, an ArrayList object. Since
> actual type parameters are erasured during compile-time, the AspectJ
> compiler just warn the programmer that this is an unchecked match (however,
> it is easy to notice that in this case it will never cause a
> ClassCastException during runtime).
>
> To show my question, take a look on the below aspect:
>
> aspect BC {
>     void around():execution(* C.*(..)) && args(List<Number>) {}  // Matchs
> C.m
>     void around():execution(* C.*(..)) && args(ArrayList<Number>) {} // DOES
> NOT MATCH C.m
> }
>
> This is exactly the same aspect I've shown before, just changing type
> parameter from Integer to Number in both args(..) constructions.
> Note that in BC aspect, the first advice follows the same semantics than the
> AC one, and then, matches  the method C.m. However,  the second advice DOES
> NOT follow the same semantics (that the AC one), and then, DOES NOT MATCH
> C.m AT ALL.
>
> My question is:
> Should not the second advice of BC aspect match the method C.m and use a
> runtime check to verify if the given parameter is an ArrayList? Some one can
> explain to me why the second advice is not matching the method C.m?
>
> The same problem is found in the following using the <? extends Number>
> aspect CC {
>     void around():execution(* C.*(..)) && args(List<? extends Number>) {}
> // Matchs C.m
>     void around():execution(* C.*(..)) && args(ArrayList<? extends Number>)
> {} // DOES NOT MATCH C.m
> }
>
>
> There exists a formal description saying how args(..) and after(..)
> returning (..) must works?
>
>
> Thanks in advance
> Fernando Rubbo
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>



-- 
Eric Bodden
Sable Research Group, McGill University, Montréal, Canada
Got an interesting job offer? http://www.bodden.de/hire-me/


Back to the top