开发者

yet another java generic question

Again I'm facing issues with generics, I thought I now know how to do this. To illustrate I created this simple example.

Given this interface

public interface Converter<A, B> {
    B encode( A a);
}

why does the following error:

void onRequest(ArrayList<String> a,Converter <? extends List<String>,String> conv) {
    conv.encode(a);
}

I expe开发者_Python百科cted that, with this notation, conv.encode would accept any param that extends List

any ideas?


Change it to:

void onRequest(ArrayList<String> a,Converter <? super List<String>,String> conv) {
    conv.encode(a);
}

You want to call encode with an ArrayList, therefore ArrayList has to be a subclass of the furst type parameter of Converter. Therefore this first type parameter has to be a super class of ArrayList. By making it be super of List this is automatically guaranteed.


The reason is that Converter <? extends List<String>,String> allows allows all Converter types with a first generic parameter that is a subtype of List, for example Converter<LinkedList, String>. If we pretend that you code could type check, in you example, that would allow you to call onRequest as:

void onRequest(ArrayList<String> a,Converter <? extends List<String>,String> conv) {
    conv.encode(a);
}

void callsOnRequest() {
    onRequest(new ArrayList<String>(), new Converter<LinkedList<String>,String>); 
}

This is not what you mean to allow.

If you replace extends by super you essentially say to the compiler that the the Converter's second parameter must be no more specific than List and thus any list (for example your ArrayList) will be assignable to the a parameter.


"? extends String" does NOT mean "any subtype of List<String>", BUT "an unknown subtype of List<String>".

Method onRequest accepts a Converter object which is parametrized with some unknown List<String> subtype. Therefore, it is saying clients that it might be passed a Converter<ArrayList<String>, String> as well as a Converter<LinkedList<String>, String> -- which is not what you want.

I think there is no need to use wildcards at all, in this example. If you want onRequest to be able to pass an ArrayList, then a Converter<List<String>, String> is enough.

You may also use a Converter<? super List<String>, String>, but this will allow clients to pass a Converter<Object, String> as well as a Converter<Collection<String>, String> etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜