4

it works.

method declaration

<T> Session<T> start(Criteria<T> criteria, List<Property<T>> orders);

usage

Criteria<? extends Product> criteria = Utils.getCriteria();
Session<? extends Product> session = null;
session = Service.start(criteria, null);

it doesn't work.

method declaration

<T> List<Session<T>> start(Criteria<T> criteria, List<Property<T>> orders)

usage

Criteria<? extends Product> criteria = Utils.getCriteria();
List<Session<? extends Product>> sessions = null;
sessions = Service.start(criteria, null);

error message

Type mismatch: cannot convert from List<Session<capture#2-of ? extends Product>> to List<Session<? extends Product>>

if I change method declaration to this, it works.

<T> List<Session<? extends T>> start(Criteria<? extends T> criteria, List<Property<? extends T>> orders)

why doen't this method declaration work?

<T> List<Session<T>> start(Criteria<T> criteria, List<Property<T>> orders)
Hiroaki Machida
  • 1,060
  • 2
  • 12
  • 23

1 Answers1

5

Here's what's happening: you are calling start() with actual parameters that are of wildcard type ? extends Product, so the compiler infers that type, substituting in a capture variable like CAP#2 for the ?, for T in the call to start. The type coming out is therefore of the type List< Session< CAP#2 > >, where all we know is that CAP#2 is-a Product.

You are trying to assign that result to a variable of type List< Session< ? extends Product > >, which represents a heterogeneous list of Sessions. I bet if you assigned it to a variable of type List< ? extends Session< ? extends Product > > it would work.

The rule is this:

( ∀S : S is-a T ) G< S > is-a G< ? extends T >                       [1]

So:

( ∀S : S is-a T ) Session< S > is-a Session< ? extends T >           [2]

In particular, since CAP#2 is-a Product, from [2] we get:

Session< CAP#2 > is-a Session< ? extends Product >                   [3]

but:

List< Session< CAP#2 > > is-NOT-a List< Session< ? extends Product > >

However, from [1] and [3] we get:

List< Session< CAP#2 > > is-a List< ? extends Session< ? extends Product > >

Anyway I recommend the following declaration to be the most generous to your clients:

< T > List< Session< T > > start(
    Criteria< ? extends T > criteria,
    List< ? extends Property< ? extends T > > orders
)
Judge Mental
  • 5,209
  • 17
  • 22