What is more flexible ?

Hi,

Reading the generics faq, I have encountered this text:

"In general, if you have an API that only uses a type parameter T as an argument, its

uses should take advantage of lower bounded wildcards (? super T). Conversely, if

the API only returns T, you抣l give your clients more flexibility by using upper bounded

wildcards (? extends T)."

Could anybody please explain me how would somebody benefit

by using this convention ? Any examples ?

Thanks,

Adrian

[518 byte] By [AdrianSosialuka] at [2007-11-27 5:32:20]
# 1
I think the FAQ has a good example:[url= http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#What%20is%20a%20bounded%20wildcard?]What is a bounded wildcard?[/url][]
S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 2

Hi,

The examples provided in this faq are quite obvious.

And the quote I had enclosed earlier is more general.

Perhaps I'm missing something here, but I still don't get

why would I benefit more using lower bounds on

arguments (apart from being able to invoke its methods,

whose signatures contain type parameter) and upper

bounds on return types (on return types ? What would I

get using it ?)

So it could look like this:

public static <T> List<? extends T> doSomething(List<? super T> l) {

return new ArrayList<T>(); // what else could I put in here ? I can't

//put just anything since I don't know what the T

//is going to be, so no subtypes available ...

//as for formal method's parameter l - there isn't

//any other benefit then being able to invoke eg:

// l.add() .... or is there something else ?

}

And the second thing is about copy method from Collections:

public static <T> void copy(List<? super T> dst, List<? extends T> src) {}

Why can't it be:

public static <T> void copy(List<? super T> dst, List<T> src) {}

I can't see any difference and the second one seems be easier to read

for me ...

Have you got any other examples ?

Cheers,

Adrian

AdrianSosialuka at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 3

but can you see any diference between this two?

public static <T> void copy( List<T> dest, List<T> src)

public static <T> void copy(List<? super T> dest, List<? extends T> src)

using the example from FAQ, it should be clear

List<Object> output = new ArrayList< Object >();

List<Long>input = new ArrayList< Long >();

Collections.copy(output,input); // illegal argument types for the first declaration above

S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 4

maybe the example of the FAQ wasn't that clear, let's try something dif.

we have a class (list) like

class MyList<T> {

private List<T> list = new ArrayList<T>();

public void add(T value) {

list.add(value);

}

}

and used here MyList<Number> list = new MyList<Number>();

list.add(new Integer(1));

list.add(new Long(2);

this works fine, (kind of an upper bound here)

now lets add a method to add a List to our MyListclass MyList<T> {

private List<T> list = new ArrayList<T>();

public void add(T value) {

list.add(value);

}

public void addAll(List<T> values) {

list.addAll(values);

}

}

and try something like List<Integer> ints = new ArrayList<Integer>();

ints.add(new Integer(3));

ints.add(new Integer(4));

MyList<Number> list = new MyList<Number>();

list.addAll(ints); // error

we get an error since we are not calling addAll with a List<Number>, but it should be possible to add Integer to a Number list....

if we had defined the addAll method in that waypublic void addAll(List<? extends T> values) {

list.addAll(values);

}

we could add all elements of a List<Integer> (or List<Long> or List<Number> or ...) to our MyList<Number>, so this is more flexible than the previous (only allowing List of Number).

[]

S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 5

Hi Simu,

That's right - an excellent example :)

Moreover - I do understand what you write here

and why it's useful here. But according to what was

written in the sun's faq (let me quote it again):

"In general, if you have an API that only uses a type parameter T as an argument, its

uses should take advantage of lower bounded wildcards (? super T). Conversely, if

the API only returns T, you抣l give your clients more flexibility by using upper bounded

wildcards (? extends T)."

An example you could fit into this convention could be (let's quote again):

public static <T> List<? extends T> doSomething(List<? super T> l) {

return new ArrayList<T>(); // what else could I put in here ? I can't

//put just anything since I don't know what the T

//is going to be, so no subtypes available ...

//as for formal method's parameter l - there isn't

//any other benefit then being able to invoke eg:

// l.add() .... or is there something else ?

}

So we accept a parameterized formal method's parameter whose

type parameter is bounded wildcard. I understand that it is useful

as we are able to call e.g.: l.add() But sometimes it is not that case

and we want to accept List<? extends T>. So why does author assume that

List<? super T> is in general better ? (Why is he assuming that in general

we want to be able to call parameter's methods which have type parameter

in its signature more often ?) And secondly, as I wrote as comment, what is

the benefit of RETURNING List<? extends T> ?

And have a look at what I wrote about copy method again:

Original from Collections:

public static <T> void copy(List<? super T> dst, List<? extends T> src) {}

My propose:

public static <T> void copy(List<? super T> dst, List<T> src) {}

They BOTH work.

Thanks for your patient :)

Cheers,

Adrian

AdrianSosialuka at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 6

first of all, note, I'm not an Generics expert, I'm just learning...

> Thanks for your patient :)

no problem, as I wrote I'm also learning a lot

====================

> public static <T> void copy(List<? super T> dst, List<? extends T> src) {}

> They BOTH work.

Yes, I also see they both work. Maybe this is not a perfect example, at least if T is not used somewhere else (other method/constructor). If we have something like

List<Object> dst;

List<Integer> src;

copy(dst, src);

T could "be" Object, Number or Integer

====================

> And secondly, as I wrote as comment, what is

> the benefit of RETURNING List<? extends T> ?

I think the tutorial does not mean the return value of a method, but an argument in which you are returning (inserting) T, like in:class MyList<T> {

private List<T> list = new ArrayList<T>();

// ...

public void copyTo(List<? super T> dst) {

dst.addAll(list);

}

}

====================

> and we want to accept List<? extends T>. So why does author assume that

> List<? super T> is in general better ? (Why is he assuming that in general

> we want to be able to call parameter's methods which have type parameter

> in its signature more often ?)

the author probably meant that using List<? super T> is better than just List<T>.

As I see it, you don't really have a choice between List<? super T> and List<? extends T>. If you insert some T into the List, it can not be List<? extends T>; if you are reading T from the List, it can not be List<? super T>; if you do both, it must be List<T>.

====================

[]

S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 7

> no problem, as I wrote I'm also learning a lot

then there are two of us ;)

> > public static <T> void copy(List<? super T> dst, List<? extends T> src) {}

> > They BOTH work.

>

> Yes, I also see they both work. Maybe this is not a

> perfect example, at least if T is not used somewhere

> else (other method/constructor).

What do you mean by saying "at least if T is not used somewhere

else (other method/constructor)" ? Could you expand on that ?

>If we have something like

> List<Object> dst;

> List<Integer> src;

> copy(dst, src)

> T could "be" Object, Number or Integer

Yeah, in both cases whether it is

public static <T> void copy(List<? super T> dst, List<? extends T> src) {}

or

public static <T> void copy(List<? super T> dst, List<T> src) {}

> > And secondly, as I wrote as comment, what is

> > the benefit of RETURNING List<? extends T> ?

>

> I think the tutorial does not mean the return value

> of a method, but an argument in which you are

> returning (inserting) T

Could you expand on that ? What do you mean by

"argument in which you are returning T" ? I didn't get it ...

> the author probably meant that using List<? super T>

> is better than just List<T>.

> As I see it, you don't really have a choice between

> List<? super T> and List<? extends T>. If you insert

> some T into the List, it can not be List<? extends

> T>; if you are reading T from the List, it can not be

> List<? super T>; if you do both, it must be List<T>.

Yeah, I agree. So I suppose he was thinking about ability

of calling parameters method like l.add() and nothing else ...

Cheers,

Adrian

AdrianSosialuka at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 8

I think it was kind of late...

> What do you mean by saying "at least if T is not used somewhere

> else (other method/constructor)" ? Could you expand on that ?

something like when you do new ArrayList<String>(), this binds the Type for all other methods like add()

> Could you expand on that ? What do you mean by

> "argument in which you are returning T" ? I didn't

> get it ...

return would be something like public List<?> something(...

by "argument in which you are returning T" I meant something like the List in public void(List<?> dst,...

if inserting something in the list

[]

S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 9

> > What do you mean by saying "at least if T is not

> used somewhere

> > else (other method/constructor)" ? Could you expand

> on that ?

>

> something like when you do new ArrayList<String>(),

> this binds the Type for all other methods like add()

Hmmm, so you say:

class MyClass<T> {

public void copy(List<? super T> dst, List<T> src) { ... }

}

Is that what you meant ? Because if it is, then no wonder

that I didn't understand it, because in the previous example

this method is static, so no connection with any other type

parameter. Unless this method is called from another

parameterized method - in that case I get it :) Am I right here ?

> > Could you expand on that ? What do you mean by

> > "argument in which you are returning T" ? I didn't

> > get it ...

>

> by "argument in which you are returning T" I meant

> something like the List in public void(List<?>

> dst,...if inserting something in the list

I'm sorry - it's maybe because of my English, but for me

return and insert are totally different words and especially

when talking about programming. I may be wrong, but I still

don't get it :/

All the best,

Adrian

AdrianSosialuka at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...
# 10

> Is that what you meant ? Because if it is, then no wonder

> that I didn't understand it, because in the previous example

> this method is static, so no connection with any other type

> parameter. Unless this method is called from another

> parameterized method - in that case I get it :) Am I

> right here ?

yes, I have not given much weight on he static part..

> I'm sorry - it's maybe because of my English, but for me

> return and insert are totally different words and especially

> when talking about programming. I may be wrong, but I still

> don't get it :/

well, my english sure is not good (nor first neither second language) so probaly I've interpreted more than I should in the "return" word....

[]]

S_i_m_ua at 2007-7-12 14:58:21 > top of Java-index,Core,Core APIs...