Kipst
Kipst

Reputation: 13

How to cope with a class which implements Comparable<?> and not Comparable<E>?

I have created an Iterator wrapper which returns elements until a certain threshold is reached as following:

public class MyIterators {
    public static <E extends Comparable<E>> Iterator<E> threshold(final Iterator<? extends E> iterator, final E threshold) {
        ...
    }
}

I want to use this for an Iterator<ChronoZonedDateTime> in a utility function as following:

public static Iterator<ZonedDateTime> oneYear(final Iterator<ZonedDateTime> iterator) {
    return MyIterators.threshold(iterator, ZonedDateTime.now().plusYears(1));
}

I am getting:

method threshold in class MyIterators cannot be applied to given types;
[ERROR]   required: java.util.Iterator<? extends E>,E
[ERROR]   found: java.util.Iterator<java.time.chrono.ChronoZonedDateTime>,java.time.ZonedDateTime
[ERROR]   reason: cannot infer type-variable(s) E
[ERROR]     (argument mismatch; java.util.Iterator<java.time.chrono.ChronoZonedDateTime> cannot be converted to java.util.Iterator<? extends java.time.chrono.ChronoZonedDateTime<?>>)

The compiler is inferring ChronoZonedDateTime instead of ZonedDateTime, while I am not declaring/using that class at all.

How do I cope with this? Do I introduce a manual cast, or is there still a way to do all this in a type-safe manner?

I am working with JDK 8.x.

Upvotes: 1

Views: 95

Answers (1)

Jacob G.
Jacob G.

Reputation: 29710

I believe the issue is caused by the raw type, ChronoZonedDateTime. If you specify a wildcard for the generic type, ChronoZonedDateTime<?>, then your code compiles and runs:

final Iterator<ChronoZonedDateTime<?>> iterator = null;
MyIterators.threshold(iterator, ZonedDateTime.now().plusYears(1));

See: What is a raw type and why shouldn't we use it?


Editing this answer as OP removed some information from the question.

Regarding your second problem, you should change <E extends Comparable<E>> to <E extends Comparable<? super E>> in the signature of threshold, which will allow you to pass in Iterator objects whose generic type is one that compares against its parent type.

The new method signature should look like the following:

public static <E extends Comparable<? super E>> Iterator<E> threshold(final Iterator<? extends E> iterator, final E threshold) {

Upvotes: 2

Related Questions