java.time.temporal.Temporal的文档包含以下说明:
执行要求:.所有实现都必须是可比较的。
为什么时态不只是扩展可比性呢?
背景:,我想使用类似的时间(而不是像LocalDateTime这样的子类型)。并且不得不求助于一个有点模糊的类型的<T extends Temporal & Comparable<T>>,这也扰乱了NetBeans的自动完成功能。
编辑:,我想实现一个时间间隔。包含(区间i)、包含(时态t)、重叠(.)、相邻(.)的明显实现等等,使用可比性::compareTo(可比c)来比较起点和终点,但是对于互操作性(toDuration(),CharSequence cs),我需要持续时间:( Temporal s,Temporal)或SubtypeOfTemporal::CharSequence(CharSequence Cs)(产生时态)。
发布于 2014-05-28 11:13:38
乍一看,@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的简化上限编写(只是时间上的),然后在运行时使用类型擦除:
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-signature的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 .。
需要注意的是:对仿制药的敌对态度不是我个人的观点。我自己可以很好地想象一个时间图书馆,它被推广了。但这是我们在这个话题中不谈的另一个话题。
发布于 2014-05-26 14:17:51
如果它实现了Comparable<Temporal>,那么每个子类实例都必须与任何其他子类实例具有可比性。例如,将Instant与LocalDate进行比较是没有意义的。
考虑到契约要求它们是可比较的,您可以将T转换为Comparable<T>,并安全地忽略编译器警告。
发布于 2014-05-26 18:46:58
有人试图实现Comparable,但是由于Temporal没有自类型泛型,所以有必要通过其子类型(如Enum)来泛化Temporal。在实践中,这不是一个很好的折衷,因为在95%+使用Temporal时,泛化的参数是未知的,因此是Temporal<?>。由于唯一泛化的解决方案对大多数用户来说是冗长和不切实际的,因此没有保留。
正如just的回答所述,在大多数情况下,您可以直接转换为Comparable。将两个输入提供给compareTo是相同的具体类型,您应该不会看到任何问题。
隔段时间,我怀疑LocalDateRange、InstantInterval和LocalTimeInterval的共同点比想象的要少,而泛化的解决方案可能比编写三个单独的类更糟糕。请记住,只要考虑了权衡,就可以选择不使用泛型。
https://stackoverflow.com/questions/23870953
复制相似问题