如何将非泛型接口扩展为通用接口?

Jin*_*won 4 java generics java-8 functional-interface

我试图扩展,TemporalAdjuster以便看起来像,

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

    T adjustInto(T temporal);
}
Run Code Online (Sandbox Code Playgroud)

当我试图直接扩展基接口时,

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

    T adjustInto(T temporal);
}
Run Code Online (Sandbox Code Playgroud)

我收到了一个错误.

... java:name clash:...有相同的擦除,但都没有覆盖另一个

有没有办法做到这一点?

到目前为止,我做到了.

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);
}
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 7

您不能覆盖具有更多限制性参数的方法,即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);
}
Run Code Online (Sandbox Code Playgroud)

然后,语义上相同的T extends Comparable<? super T> & Temporal被删除Comparable而不是Temporal.您也可以使用T extends Object & Comparable<? super T> & Temporal哪些被删除Object(通常,只有当您需要与前Generics代码兼容时,此类知识才有用).

然而,根本的问题仍然存在,adjustInto(T temporal);不会覆盖adjustInto(Temporal temporal);T是更严格的参数,所以现在,接口不是一个功能接口了,因为它有两个抽象方法.

TemporalAdjuster必须提供其所有操作的子接口,包括adjustInto接受任何操作Temporal.所以你只能这样做

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,这样的包装调整器无法确保正确的参数,只能隐藏仍然可能在运行时失败的类型转换.但是看起来你正试图在这里解决一个不存在的问题,因为你可以简单地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);
Run Code Online (Sandbox Code Playgroud)

这比你的包装更强大,就像你做的那样,例如

TemporalAdjuster a = TemporalAdjusters.ofDateAdjuster(date -> date.plusDays(1));

ZonedDateTime zoned1 = ZonedDateTime.now(), zoned2 = zoned1.with(a);
Run Code Online (Sandbox Code Playgroud)

您定义的操作只有一次,在方面LocalDate操作,同时通过将它们即时的,而不是铸造适用于其他temporals.