【问题标题】: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&lt;T&gt; 实例并获得一个名为sum 的方法,该方法通过反射将两个Ts 作为参数。但是,我不确定我是否会推荐这种方法而不是当前的实现,因为当前的实现对我来说看起来非常好。

标签: java sum binary-operators


【解决方案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 类时,您需要为 TN 提供泛型类型 - 例如:

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

    (或者,很明显,在那里放入非通配符类型,如果您可以添加有用的类型)。

    如果不需要,请从类中删除类型参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多