乍一看,@JBNizet 的答案对我来说非常模糊,因为他建议对Comparable
(忽略编译器警告)进行简单的类型转换,通常我更喜欢没有任何类型转换或警告的代码(它们不只是为了有趣),但首先现在我有时间更仔细地调查整个事情。让我们考虑以下简单的区间示例:
public class FlexInterval<T extends Temporal & Comparable<T>> {
private final T from;
private final T to;
public FlexInterval(T from, T to) {
super();
this.from = from;
this.to = to;
}
public boolean contains(T test) {
return (this.from.compareTo(test) <= 0) && (this.to.compareTo(test) >= 0);
}
}
在此基础上(据我了解,OP 首选),编译器将拒绝以下代码中的第一行是合乎逻辑的:
FlexInterval<LocalDate> interval =
new FlexInterval<LocalDate>(today, today); // compile-error
System.out.println(interval.contains(LocalDate.of(2013, 4, 1));
原因是LocalDate
没有实现Comparable<LocalDate>
但是Comparable<ChronoLocalDate>
。因此,如果我们改用@JBNizet 的方法并使用 T 的简化上限(只是 Temporal)编写,然后在运行时使用类型擦除:
public class FlexInterval<T extends Temporal> {
...
@SuppressWarnings("unchecked") // code smell!
public boolean contains(T test) {
Comparable<T> t1 = (Comparable<T>) this.from;
Comparable<T> t2 = (Comparable<T>) this.to;
return (t1.compareTo(test) <= 0) && (t2.compareTo(test) >= 0);
}
}
此代码编译。在运行时:
FlexInterval<LocalDate> interval =
new FlexInterval<LocalDate>(today, today);
System.out.println(interval.contains(LocalDate.of(2013, 4, 1));
// output: false
都好吗?不。一个负面的例子表明了新的通用签名的不安全FlexInterval
性(编译器警告有其原因)。如果我们只是在运行时选择一个抽象类型(一些用户可能会在“通用”(坏)辅助类中这样做):
LocalDate today = LocalDate.now();
FlexInterval<Temporal> interval = new FlexInterval<Temporal>(today, today);
System.out.println(interval.contains(LocalDate.of(2013,4,1))); // output: false
System.out.println(interval.contains(LocalTime.now()));
...然后代码再次编译,但我们得到:
Exception in thread "main" java.lang.ClassCastException: java.time.LocalTime can
not be cast to java.time.chrono.ChronoLocalDate
at java.time.LocalDate.compareTo(LocalDate.java:137)
at FlexInterval.contains(FlexInterval.java:21)
结论:
类型安全强烈要求自引用泛型(JSR-310 不支持)和具体类型。由于 JSR-310 团队有意尽可能避免使用泛型,因此愿意使用 JSR-310 的用户应该尊重这一设计决策,并在其应用程序代码中避免使用泛型。最好建议用户只使用具体的最终类型,而不使用通用的泛型类(这不是完全安全的)。
最重要的一课:避免Temporal
在任何应用程序代码中使用接口。
需要注意的是:对仿制药的敌对态度不是我个人的看法。我自己可以很好地想象一个泛型的时间库。但这是我们在本主题中不讨论的另一个主题。