Reputation: 445
I have the following (obviously useless in this form) Java class:
public class EntrySet<T> {
public static class Entry<T> {
T obj;
}
private final Set<Entry<T>> set;
public EntrySet() {
this.set = Sets.newHashSet();
}
public Set<Entry<T>> getEntries() {
return set;
}
}
Given this class, the following does not compile:
EntrySet<?> entrySet = new EntrySet<SomeClass>();
Set<EntrySet.Entry<?>> entries = entrySet.getEntries();
The second line has the compile error "cannot convert from Set<EntrySet.Entry<capture#1-of ?>>
to Set<EntrySet.Entry<?>>
". I cannot find a way to eliminate this error, even with casting or using a helper function.
What exactly is the issue here, and is there a way to get a clean compile?
The best I could do is:
EntrySet<?> entrySet = new EntrySet<SomeClass>();
Set<?> tmp = entrySet.getEntries();
Set<EntrySet.Entry<?>> entries = (Set<EntrySet.Entry<?>>) tmp;
which is obviously terrible (even with the relevant warning suppression).
Upvotes: 1
Views: 134
Reputation: 612
The unbounded wild card <?>
is like the super-type of all generic types. It is similar to what an Object class is to all java classes. The only operations that you can perform on a unbounded wildcard reference are those which take a 'null' (if <?>
parameter is used in the argument reference) or those that return a 'Object' (if <?>
parameter is used in the return type reference). So your code will compile if it returns a reference of the type Object.
class EntrySet<T> {
public static class Entry<T> {
T obj;
}
private final java.util.Set<Entry<T>> set;
public EntrySet() {
this.set = new java.util.HashSet();
}
public java.util.Set<Entry<T>> getEntries() {
return set;
}
public static void main(String [] args){
EntrySet<?> entrySet = new EntrySet<SomeClass>();
//java.util.Set<EntrySet.Entry<?>> entries = entrySet.getEntries(); // Error
Object o = entrySet.getEntries(); // OK !
}
}
class SomeClass{}
Upvotes: 0
Reputation: 147154
Removing entrySet
you are attempting to assign a Set<EntrySet.Entry<SomeClass>>
to Set<EntrySet.Entry<?>>
. There are hundreds of Stack Overflow questions which are essentially the same thing. You could add a EntrySet.Entry<OtherClass>
to the latter but not the former, so that would break type-safety.
Probably the way to deal with this is to capture the wild card by calling a method with a (named) generic parameter.
EntrySet<?> entrySet = new EntrySet<SomeClass>();
fn(entrySet);
...
private static <T> void fn(EntrySet<T> entrySet) {
Set<EntrySet.Entry<T>> entries = entrySet.getEntries();
Upvotes: 1