如何从类中获取二元运算符?
Posted
技术标签:
【中文标题】如何从类中获取二元运算符?【英文标题】:How can I get a Binary Operator from a Class? 【发布时间】:2021-08-12 21:57:14 【问题描述】:有没有办法获得与类相关的二元运算符? 我有这个方法有两个参数:
public <T extends Number> T[] sumArray(T[] arrayToAdd, BinaryOperator<T> add)
T[] arrayToReturn = arrayToAdd.clone();
for (int i = 0; i < arrayToAdd.length; i++)
arrayToReturn[i] = arrayToAdd[i];
for (int j = 0; j < i; j++)
arrayToReturn[i] = add.apply(arrayToReturn[i], arrayToAdd[j]);
return arrayToReturn;
但是,我想做这样的事情:
public <T extends Number> T[] sumArray(T[] arrayToAdd)
BinaryOperator add = arrayToAdd.getClass().getBinaryOperator(sum);
T[] arrayToReturn = arrayToAdd.clone();
for (int i = 0; i < arrayToAdd.length; i++)
arrayToReturn[i] = arrayToAdd[i];
for (int j = 0; j < i; j++)
arrayToReturn[i] = add.apply(arrayToReturn[i], arrayToAdd[j]);
return arrayToReturn;
重要提示: .getBinaryOperator(sum)
方法不存在。
PD:从另一个类调用第一种方法时,我也遇到了问题:
api.sumArray(intArray, Integer::sum);
错误说:'Object is not convertible to int'
------------------编辑------------------
最小的可重现示例
public class guide6Main<T extends Comparable<T>, N extends Number>
public static void main(String[] args)
ApiArray api = new ApiArray();
Integer[] intArray = 1, 2, 3, 4;
api.exercise6(intArray, Integer::sum);
public class ApiArray<T extends Comparable<T>, N extends Number>
public <N extends Number> N[] exercise6(N[] arrayToAdd, BinaryOperator<N> add)
N[] arrayToReturn = arrayToAdd.clone();
for (int i = 0; i < arrayToAdd.length; i++)
arrayToReturn[i] = arrayToAdd[i];
for (int j = 0; j < i; j++)
arrayToReturn[i] =add.apply(arrayToReturn[i],arrayToAdd[j] );
return arrayToReturn;
这是错误:
D:\Documentos\Austral\Álgerba III\src\Guia6\Team2Solution\guide6Main.java:11:49
java: incompatible types: invalid method reference
incompatible types: java.lang.Object cannot be converted to int
P.D.2:另外,arrayToAdd
不能包含混合类型,我的意思是,它可以,但在这种情况下不是
(最小的可重现示例可以吗?我从来没有做过这样的事情)
【问题讨论】:
"intArray
" 是int[]
还是Integer[]
?
“我想做这样的事情”对不起,你不能,至少不能以完全通用的方式。毕竟,arrayToAdd
可能包含多种类型(例如,一些 Double
、一些 Integer
、一些 BigInteger
)。
@AndyTurner Integer[]
.
请显示一个minimal reproducible example,它重现了“Object is not convertible to int”错误。
type erasure 的性质使得很难按照问题中提出的方式进行操作。但是,应该可以传递一个Class<T>
实例并获得一个名为sum
的方法,该方法通过反射将两个T
s 作为参数。但是,我不确定我是否会推荐这种方法而不是当前的实现,因为当前的实现对我来说看起来非常好。
【参考方案1】:
此时你的班级设计并不是最优的。
你的方法隐藏了N
的类参数。
所以当你这样做时
ApiArray api = new ApiArray();
Integer[] intArray = 1, 2, 3, 4;
api.exercise6(intArray, Integer::sum);
您使用的是原始类型(请参阅 ApiArray api 而不提供类型),这将导致 N
只是 object
,因为此时 N
未绑定到任何类型.这将导致N
被擦除为Object
,因为Object
是最不超级的类型。
因此,在实例化 ApiArray
类时,您需要为 T
和 N
提供泛型类型 - 例如:
ApiArray<Integer, Integer> api = new ApiArray();
Integer[] intArray = 1, 2, 3, 4;
api.exercise6(intArray, Integer::sum );
实现结果的另一种方法是删除类的泛型类型边界:
class ApiArray
public <N extends Number> N[] exercise6(N[] arrayToAdd, BinaryOperator<N> add)
N[] arrayToReturn = arrayToAdd.clone();
for (int i = 0; i < arrayToAdd.length; i++)
arrayToReturn[i] = arrayToAdd[i];
for (int j = 0; j < i; j++)
arrayToReturn[i] =add.apply(arrayToReturn[i],arrayToAdd[j] );
return arrayToReturn;
这里的泛型类型/边界由方法签名提供。
另一种方法是从您的方法中删除泛型类型参数,并使用类本身的泛型类型参数边界:
class ApiArray<T extends Comparable<T>, N extends Number>
public N[] exercise6(N[] arrayToAdd, BinaryOperator<N> add)
N[] arrayToReturn = arrayToAdd.clone();
for (int i = 0; i < arrayToAdd.length; i++)
arrayToReturn[i] = arrayToAdd[i];
for (int j = 0; j < i; j++)
arrayToReturn[i] =add.apply(arrayToReturn[i],arrayToAdd[j] );
return arrayToReturn;
ApiArray<Integer, Integer> api = new ApiArray();
Integer[] intArray = 1, 2, 3, 4;
api.exercise6(intArray, Integer::sum );
【讨论】:
【参考方案2】:纯粹回答错误“incompatible types: java.lang.Object cannot be converted to int
”:
public class guide6Main<T extends Comparable<T>, N extends Number>
public static void main(String[] args)
ApiArray api = new ApiArray();
Integer[] intArray = 1, 2, 3, 4;
api.exercise6(intArray, Integer::sum);
public class ApiArray<T extends Comparable<T>, N extends Number>
public <N extends Number> N[] exercise6(N[] arrayToAdd, BinaryOperator<N> add)
// ...
ApiArray
是泛型类型,但ApiArray api
是原始类型变量(它没有类型参数)。
原始类型会擦除所有泛型,甚至那些与省略的类型参数无关的泛型。
要么使用通配符类型声明api
:
ApiArray<?, ?> api = new ApiArray<>();
(或者,很明显,在那里放入非通配符类型,如果您可以添加有用的类型)。
如果不需要,请从类中删除类型参数。
【讨论】:
以上是关于如何从类中获取二元运算符?的主要内容,如果未能解决你的问题,请参考以下文章
如何从类中获取“ReadOnly”或“WriteOnly”属性?