我如何正确限制通用接口在 Java 中扩展 Number class 并能够在另一个 class 中 运行?
How do I correctly restrict a generic interface to extend Number class in Java and be able to run it in another class?
我正在尝试了解如何扩展接口并在另一个接口中使用它 class,但每次编译器都会抛出转换错误。我曾尝试在 printResult 方法中使用通配符,但它不起作用。这里可能是什么问题?它只适用于整数。
public interface Computable <T extends Number>
{
public T compute(T x, T y);
}
------------------------------------------------------------
public class TestComputable
{
public static void main(String[] args)
{
Computable<Float> comp;
comp = (x, y) -> x + y;
printResult(comp);
}
}
public static void printResult(Computable compIn)
{
System.out.println("The result is: " + compIn.compute(10, 5));
}
这是编译器实际尝试通过发出有关使用原始类型的警告来帮助您的地方:如果您更改 printResult
方法以使用正确的类型参数,如下所示:
public static void printResult(Computable<Float> compIn) { // instead of Computable compIn
那么编译器会在编译时显示错误:
// Now the compiler throws error:
// the method compute(Float, Float) is not applicable for the arguments (int, int)
System.out.println("The result is: " + compIn.compute(10, 5));
这就是为什么你应该始终避免使用原始类型,编译器可以推断出正确的类型绑定。
现在我们有了编译错误信息,我们知道问题出在哪里了:参数 10
和 5
是 int
值,而接口 Computable
需要 Float
个值,因此您可以将它们修复为浮点值:
System.out.println("The result is: " + compIn.compute(10f, 5f));
您的代码将仅适用于 Integer,因为您将 Integer 参数传递给 Computable。
如果你想传入例如“Float等价于Integer”,需要传入一个Function将Integer转换为Float;更一般地说,如果你想传入“整数的 T 等价物”,你需要传入一个函数来将整数转换为 T:
public static <T extends Number> void printResult(Computable<T> compIn, Function<? super Integer, ? extends T> fn)
{
System.out.println("The result is: " + compIn.compute(fn.apply(10), fn.apply(5)));
}
并像这样调用:
printResult(comp, Integer::floatValue);
或者,您可以显式传递正确类型的参数:
public static <T extends Number> void printResult(Computable<T> compIn, T a, T b) {
// ... Something with compln.compute(a, b)
}
并像这样调用:
printResult(comp, 10.f, 5.f);
在不传递额外参数的情况下使这项工作起作用的唯一方法是只接受可以接受任何数字的 Computable
,或者至少可以接受您传入的类型的参数:
public static void printResult(Computable<Number> compIn) { ... }
public static void printResult(Computable<Integer> compIn) { ... }
public static void printResult(Computable<? super Integer> compIn) { ... }
我正在尝试了解如何扩展接口并在另一个接口中使用它 class,但每次编译器都会抛出转换错误。我曾尝试在 printResult 方法中使用通配符,但它不起作用。这里可能是什么问题?它只适用于整数。
public interface Computable <T extends Number>
{
public T compute(T x, T y);
}
------------------------------------------------------------
public class TestComputable
{
public static void main(String[] args)
{
Computable<Float> comp;
comp = (x, y) -> x + y;
printResult(comp);
}
}
public static void printResult(Computable compIn)
{
System.out.println("The result is: " + compIn.compute(10, 5));
}
这是编译器实际尝试通过发出有关使用原始类型的警告来帮助您的地方:如果您更改 printResult
方法以使用正确的类型参数,如下所示:
public static void printResult(Computable<Float> compIn) { // instead of Computable compIn
那么编译器会在编译时显示错误:
// Now the compiler throws error:
// the method compute(Float, Float) is not applicable for the arguments (int, int)
System.out.println("The result is: " + compIn.compute(10, 5));
这就是为什么你应该始终避免使用原始类型,编译器可以推断出正确的类型绑定。
现在我们有了编译错误信息,我们知道问题出在哪里了:参数 10
和 5
是 int
值,而接口 Computable
需要 Float
个值,因此您可以将它们修复为浮点值:
System.out.println("The result is: " + compIn.compute(10f, 5f));
您的代码将仅适用于 Integer,因为您将 Integer 参数传递给 Computable。
如果你想传入例如“Float等价于Integer”,需要传入一个Function将Integer转换为Float;更一般地说,如果你想传入“整数的 T 等价物”,你需要传入一个函数来将整数转换为 T:
public static <T extends Number> void printResult(Computable<T> compIn, Function<? super Integer, ? extends T> fn)
{
System.out.println("The result is: " + compIn.compute(fn.apply(10), fn.apply(5)));
}
并像这样调用:
printResult(comp, Integer::floatValue);
或者,您可以显式传递正确类型的参数:
public static <T extends Number> void printResult(Computable<T> compIn, T a, T b) {
// ... Something with compln.compute(a, b)
}
并像这样调用:
printResult(comp, 10.f, 5.f);
在不传递额外参数的情况下使这项工作起作用的唯一方法是只接受可以接受任何数字的 Computable
,或者至少可以接受您传入的类型的参数:
public static void printResult(Computable<Number> compIn) { ... }
public static void printResult(Computable<Integer> compIn) { ... }
public static void printResult(Computable<? super Integer> compIn) { ... }