I expected the first one to be correct.
As ZonedDateTime implements ChronoZonedDateTime<LocalDate>
, I tried to use latter as type parameter. I guess this didn't work due to type erasure, but I'm not sure.
But only third range is compiled correctly. Could you please explain why?
import org.apache.commons.lang3.Range;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.chrono.ChronoZonedDateTime;
public class Test {
public static void main(String[] args) {
Range<ZonedDateTime> range1 = Range.between(ZonedDateTime.now(), ZonedDateTime.now());
Range<ChronoZonedDateTime<LocalDate>> range2 = Range.between(ZonedDateTime.now(), ZonedDateTime.now());
Range<ChronoZonedDateTime<?>> range3 = Range.between(ZonedDateTime.now(), ZonedDateTime.now());
}
}
The Range.between(T fromInclusive, T toInclusive)
returns a Range<T>
object, where T
must extend Comparable<T>
. We can see this from the JavaDoc.
You want to use ZonedDateTime
objects for your T
. And looking at that JavaDoc, we see that it implements Comparable<ChronoZonedDateTime<?>>
.
That is why you have to use Range<ChronoZonedDateTime<?>>
as the type for the returned value.
It's not type erasure which causes compilation errors with your first two examples. It's just the need to follow the APIs of the objects you are using. The first two examples don't meet the requirement to provide the correct generic object which implements Comparable
.
Another perspective:
The values of T
from your original between(T fromInclusive, T toInclusive)
need to be naturally comparable, just like the values in this much simpler example for the same generic method:
Range<Integer> range = Range.between(1, 9);
...where the Java Integer
class implements Comparable<Integer>
.
You can use objects which are not naturally comparable, but then you have to provide your own comparator:
public static <T> Range<T> between(T fromInclusive, T toInclusive, Comparator<T> comparator)
...and your comparator would have to provide the comparison rules.