您不能使用更严格的参数覆盖一个方法,例如
T adjustInto(T temporal);
无法覆盖
Temporal adjustInto(Temporal temporal);
,因为参数类型
T
比
Temporal
更严格。因此,现在您有两个名为
adjustInto
的方法,但由于类型擦除,在字节码级别上参数类型是相同的,因为
T extends Temporal & Comparable<? super T>
被擦除为
Temporal
。
您可以通过更改声明来解决这个问题:
public interface TypedTemporalAdjuster<T extends Comparable<? super T> & Temporal>
extends TemporalAdjuster {
T adjustInto(T temporal);
}
作为语义相同的
T extends Comparable<? super T> & Temporal
会被擦除为
Comparable
而不是
Temporal
。你也可以使用
T extends Object & Comparable<? super T> & Temporal
,它被擦除为
Object
(通常,这种知识只有在需要与预泛型代码兼容时才相关)。
然而,根本问题仍然存在,
adjustInto(T temporal);
没有覆盖
adjustInto(Temporal temporal);
,因为
T
是更严格的参数,所以现在接口不再是功能接口,因为它有两个抽象方法。
TemporalAdjuster
的子接口必须提供其所有操作,包括接受任何
Temporal
的
adjustInto
。所以你只能这样做:
public interface TypedTemporalAdjuster<T extends Temporal & Comparable<? super T>>
extends TemporalAdjuster {
static <T extends Temporal & Comparable<? super T>> TypedTemporalAdjuster<T> of(
final Class<T> temporalClass, final TemporalAdjuster temporalAdjuster) {
return temporal -> temporalClass.cast(temporalAdjuster.adjustInto(temporal));
}
@Override T adjustInto(Temporal temporal);
}
然而,这样包装的调整器不能确保正确的参数,并且只是隐藏了类型转换,仍然可能在运行时失败。但似乎你在尝试解决一个不存在的问题,因为你可以简单地使用暂存的
with
方法来获得类型安全的操作,例如:
TemporalAdjuster a = TemporalAdjusters.lastDayOfMonth();
LocalDate date1 = LocalDate.now(), date2 = date1.with(a);
LocalDateTime dateTime1 = LocalDateTime.now(), dateTime2 = dateTime1.with(a);
ZonedDateTime zoned1 = ZonedDateTime.now(), zoned2 = zoned1.with(a);
这甚至比你的包装器更强大,因为当你这样做时,例如:
TemporalAdjuster a = TemporalAdjusters.ofDateAdjuster(date -> date.plusDays(1))
ZonedDateTime zoned1 = ZonedDateTime.now(), zoned2 = zoned1.with(a)
您仅需一次定义一个操作,使用 LocalDate
操作,即可通过在运行时将其转换而不是强制转换其他时间使其适用于其他时间。
@Override default Temporal adjustInto(Temporal temporal) { return adjustInto2((T) temporal); } T adjustInto2(T temporal);
。这仍然是一个功能接口。 - ernest_k