我正在尝试扩展 TemporalAdjuster ,使它看起来像,

public interface TypedTemporalAdjuster<T extends Temporal & Comparable<? super T>> {

    T adjustInto(T temporal);
}

当我尝试直接扩展基本接口时,

public interface TypedTemporalAdjuster<T extends Temporal & Comparable<? super T>>
        extends TemporalAdjuster {

    T adjustInto(T temporal);
}

我有一个错误。

... java:名称冲突:...具有相同的擦除,但是没有一个覆盖另一个

有什么办法吗?

到目前为止,我做到了。

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(temporalClass.cast(temporal)));
    }

    T adjustInto(T temporal);
}

最佳答案

您不能覆盖具有更多限制性参数的方法,即T adjustInto(T temporal);不会覆盖Temporal adjustInto(Temporal temporal);,因为参数类型TTemporal更具限制性。因此,您现在有两种名称为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的子接口必须提供其所有操作,包括一个接受任何adjustIntoTemporal。所以你只能做
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操作而言,您只定义一次操作,而通过即时转换而不是强制转换将其用于其他时态,则该操作适用于其他时态。

08-06 08:00