能否通过F-界量化在带默认实现的泛型接口中返回this?
如何用F-界量化在IOrd接口的min方法中返回this?
先看看你给出的代码,这里确实存在类型不匹配的问题:
public interface IEq<T> { public abstract Boolean testEqual(final T y); public default Boolean testNotEqual(final T y) { return !this.testEqual(y); } } public interface IOrd<T> extends IEq<T> { public abstract Boolean lessEqualThan(final T y); public default T min(final T y) { if(lessEqualThan(y)) return this; // <--- ERROR: cannot convert from IOrd<T> to T else return y; } }
问题根源
编译器报错的原因很直接:this代表的是IOrd<T>接口的实现实例,但min方法的返回类型是T——编译器不知道IOrd<T>和T之间有什么继承关系,自然不允许这种类型转换。而你提到的F-界量化,正是解决这类泛型中"自身类型引用"问题的标准方案。
解决方案:调整泛型声明为F-界形式
我们只需要修改IOrd接口的泛型参数约束,让T必须是实现了IOrd<T>的类型,这样就能建立起this和T的类型关联:
public interface IEq<T> { public abstract Boolean testEqual(final T y); public default Boolean testNotEqual(final T y) { return !this.testEqual(y); } } // 使用F-界量化:T extends IOrd<T> public interface IOrd<T extends IOrd<T>> extends IEq<T> { public abstract Boolean lessEqualThan(final T y); public default T min(final T y) { if(lessEqualThan(y)) return (T) this; // 此时转型是安全的,因为T必然是IOrd<T>的子类型 else return y; } }
为什么这样可行?
通过T extends IOrd<T>这个约束,我们告诉编译器:泛型参数T必须是一个实现了IOrd<T>的类型。这意味着任何实现IOrd的类,都要把自己作为泛型参数传入(比如class MyType implements IOrd<MyType>)。此时this(IOrd<T>的实例)本质上就是T类型的实例,所以向下转型是完全安全的,编译器也会认可这个转换。
举个实际实现的例子
比如我们写一个处理整数的IntOrd类:
public class IntOrd implements IOrd<IntOrd> { private final int value; public IntOrd(int value) { this.value = value; } @Override public Boolean testEqual(IntOrd y) { return this.value == y.value; } @Override public Boolean lessEqualThan(IntOrd y) { return this.value <= y.value; } public static void main(String[] args) { IntOrd a = new IntOrd(3); IntOrd b = new IntOrd(5); IntOrd min = a.min(b); System.out.println(min.value); // 输出3 } }
运行这段代码,min方法就能正常返回this(也就是a实例),完全符合预期。
内容的提问来源于stack exchange,提问作者chansey
相关产品推荐
相关产品推荐

