有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我试图扩展^{},这样看起来

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: name clash: ... have the same erasure, yet neither overrides the other

有没有办法做到这一点

到目前为止,我做到了

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);
}

共 (1) 个答案

  1. # 1 楼答案

    您不能用更严格的参数重写方法,即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的子接口必须提供其所有操作,包括接受任何TemporaladjustInto。所以你只能这样做

    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操作,您只定义一次操作,而它通过动态转换而不是强制转换来为其他临时对象工作