Giving a wildcard a name
I am pulling this out from another thread and reposting it because the issue stand on its own. Let Tag be some interface and Foo another interface parametrized over Tag, i.e., declared as Foo<T extends Tag>. I don't understand the difference between
<Textends Tag> Foo<T> test()
and
Foo<?extends Tag> test()
[425 byte] By [
xolotla] at [2007-11-27 1:23:25]

# 1
confused by description
> ... Let Tag be some interface and Foo another interface
> parametrized over Tag, i.e., declared as Foo<T
> extends Tag>. I don't understand the difference
> between
> <T extends Tag> Foo<T> test()
> and
> Foo<? extends Tag> test()
As a type declaration interface Foo<T extends Tag>
is valid, but interface Foo<? extends Tag>
is not ("?" invalid TypeParameter).
As a pure method declaration (interface or abstract), they appear functionally equivalent. There is no need to name the parameterized return type (T or ? will suffice), but as a method implementation <T extends Tag> Foo<T> test()
allows the implementor to use the parameterized type, T. This may or may not be needed depending on the implementation.
Being a generics rookie, I am interested in other postings.
# 2
Hum, maybe it's easier to see with known objects:<T extends Number> List<T> listOfT() { return null; }
List<? extends Number> listOfNumbers() { return null; }
Is this more obvioius? The first returns a list containing T typed elements, it is bound to the inferred type when calling listOfT(). The second returns a list containing instances of unknown type being subclass of Number.
For APIs it's usually advisable to use wildcards in such cases and handle binding to a type parameter internally only.
# 3
developer_jbs, yes of course I meant these two snippets as method signatures. That there is in fact a difference can be seen from the code in the "Interaction between covariance and generics" (3rd post).
Stefan, I assume that in most (all?) circumstances the "? extends Number" will be captured and "capture of ? extends Number" is AFAICT the same as "T extends Number" except the compiler does not give a dummy name to the captured type. So I still don't see why, e.g., in the code referred to above, you get a warning in one case but not in the other.
And yes in general you shouldn't give a name to a wilcard type but, as we have seen in the first of this series of threads ("Implied types") there are times when you are forced to, which is why it's unfortunate that it (apparently) changes the semantics.
# 4
Maybe our host could chime in? On his blog there is an entry: http://www.reason.com/john.sugg@creativeloafing.com in which he repeats the advice not to gratuitously give a wildcard a name but he offers it as a best practice suggestion only: he gives no inkling that there is a semantic difference between the two. So, is there one or not?
# 5
<T extends Number> List<T> listOfT() { return null; }
Means: for all T that are a subtype of Number:
List<T> listOfT() { return null; }
In other words, if you tell the method what T is, it can return a List<T>.
List<? extends Number> listOfNumbers() { return null; }
Means: there exists a T which is a subtype of Number:
List<T> listOfT() { return null; }
In other words, you do not know what T is, only that it exists.
# 6
> In other words, if you tell the method what T is, it can return a List<T>.
Oh, I see now. You mean it behaves like one of those factory methods used to create collections of a certain kind w/o having to repeat the type in the rhs of the assignment, i.e., the caller, not the callee, decides which type is returned and thus must provide it. Correct?
But then what do you suggest to handle the situation whereby one wants to return something like
<T extends Tag> Bar<T, ? extends Foo><T>> method() { ... }
Here I am not naming T because I want a factory method: I do not know what T will be when I call that method, but because
Bar<? extends Tag, ? extends Foo<? extends Tag>> method() { ... }
would fail to constrain the first Tag to be the same as the Tag that Foo is parametrized over. Giving that Tag a name seems the only way but apparently that completely changes the semantics of the method. Am I stuck?
# 7
> <T extends Tag> Bar<T, ? extends Foo><T>> method()
> { ... }
I don't think this method will help on the users side, as it has no clue about T unless method takes some parameter that depends on it or you plan to infer the type from the caller (compare the Collections class on creating empty sets and lists). Thus:
> Bar<? extends Tag, ? extends Foo<? extends Tag>>
> method() { ... }
would serve the same purpose for your case, as the kind of Tag is determined within the method (where you have control over Tag and Foo matching your requirements) and the receiver will act upon unknown generic arguments.
# 8
I think you are missing my point on two counts, so let me clarify again.
First, this is not the only method in the system and I need type information to flow through it, with constraints. To see what I mean, try to compile the following and see the error you get; you can't pass the output of f2 to f3. The Tag type my well meet the constraint imposed in the Bar declaration (in fact it will have to) but that information is lost in the declaration of f2 and the compiler won't infer it for you.
public class Test2 {
public static final void main(String[] argv) {
f3(f1());
f3(f2());
}
public static <T extends Tag> Bar<T, ? extends Foo><T>> f1() { return null; }
public static Bar<? extends Tag, ? extends Foo<? extends Tag>> f2() { return null; }
public static <T extends Tag> void f3(Bar<T, ? extends Foo><T>> x) {}
}
interface Tag { }
interface Foo<T extends Tag> {}
interface Bar<T extends Tag, F extends Foo><T>> { }
> the kind of Tag is determined within the method
As I already said, I do not care about the precise Tag indeed and I understand now that f1, as a kind of factory method that lets you specify it, is not what is needed here, but AFAICT there is no other way to return some random Bar w/o losing the needed relationship between its type parameters. If you know one, please show it to me.
