0

I have a variable of type:

Iterable<Map<String,Object>>

and I am trying to return it as type:

Iterable<Map<String,?>>

The compiler says:

argument mismatch; Iterable<Map<String,Object>>
cannot be converted to Iterable<Map<String,?>>

Does anybody know how to coerce the compiler into "doing the right thing" here, or is this somehow impossible?

3 Answers3

1

You can always cast to an untyped Iterable and let the return statement perform an unchecked cast back to the type you want:

public static Iterable<Map<String, ?>> getIt() {
    Iterable<Map<String, Object>> t = null;
    return ((Iterable) t);
}
BarrySW19
  • 3,759
  • 12
  • 26
1

Iterable<T> should is a "Producer" of Iterator<T>, which is in turn a "Producer" of its type parameter T (there is only a method that returns T, and no method that takes T). Therefore, according to the PECS (Producer extends, Consumer super) rule, it should always be used with extends wildcards everywhere.

If you have a variable of type

Iterable<? extends Map<String,Object>>

and you return it as

Iterable<? extends Map<String,?>>

there is no problem. Whenever you get Iterator out of it, you will similarly type it as Iterator<? extends Something>.

newacct
  • 119,665
  • 29
  • 163
  • 224
0

If you don't want to use the bludgeon method of just casting to the raw type (which can cause grief - see What is a raw type and why shouldn't we use it?) you could always use a thin adapter requiring no casting at all thus maintaining all possible type safety:

// Could probably be done inline with a little tweaking.
class IMSQ implements Iterable<Map<String, ?>> {

    // The adaptee.
    final Iterable<Map<String, Object>> o;

    public IMSQ(Iterable<Map<String, Object>> o) {
        this.o = o;
    }

    @Override
    public Iterator<Map<String, ?>> iterator() {
        // Pull a new Iterator out of it.
        final Iterator<Map<String, Object>> it = o.iterator();
        // Wrap it.
        return new Iterator<Map<String, ?>>() {

            @Override
            public boolean hasNext() {
                return it.hasNext();
            }

            @Override
            public Map<String, ?> next() {
                return it.next();
            }

        };
    }

}
Community
  • 1
  • 1
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213