Кастинг для Lambda: BiConsumer - PullRequest
0 голосов
/ 26 июня 2019

Я получаю ошибку компилятора, например: Метод accept (Integer, Integer) в типе BiConsumer не применим для аргументов (Object, Object). Как я могу привести два целочисленных ввода, чтобы компилятор принял их как <Integer, Integer>?

Я получаю ошибку в следующем коде:

import java.util.function.BiConsumer;

public class ExceptionHandlingExample {

    public static void main(String[] args) {
        int[] numberArray = { 1, 2, 3, 4 };
        int key = 2;
        calc(numberArray, key, wrapperForLambda( (a, b) -> System.out.println(a / b) ));
        // Type Safety: The expression of Type BiConsumer needs unchecked conversion to conform to unchecked BiConsumer<Integer, Integer>
    }

    private static void calc(int[] numberArray, int key, BiConsumer<Integer, Integer> consumer) {
        for (int i : numberArray) {
            consumer.accept(i, key);
        }
    }

    private static BiConsumer wrapperForLambda(BiConsumer<Integer, Integer> consumer) {
    // BiConsumer is a raw type. References to generic type BiConsumer<T, U> should be parameterized       
        return (a, b) -> consumer.accept(a, b) ;   
    // [Compilier-error] The method accept (Integer, Integer) in the type BiConsumer<Integer, Integer> is not applicable for the arguments (Object, Object) 
    }
}

Я хочу избавиться от ошибки компилятора: Метод accept (Integer, Integer) в типе BiConsumer не применим для аргументов (Object, Object)

Заранее благодарю за помощь!

Ответы [ 4 ]

2 голосов
/ 26 июня 2019

Я не знаю, какова цель wrapperForLambda. Тебе это не нужно. Просто позвоните calc следующим образом:

calc(numberArray, key, (a, b) -> System.out.println(a / b));

И ошибку в wrapperForLambda можно устранить с помощью:

private static BiConsumer wrapperForLambda(BiConsumer<Integer, Integer> consumer) {
     return consumer;
}

но я все еще считаю этот метод бессмысленным.

P.S. Я предполагаю, что цикл в методе calc должен повторяться в массиве someNumbers, а не numberArray (который является локальной переменной вашего метода main).

2 голосов
/ 26 июня 2019

Не используйте необработанный тип BiConsumer.Объявите метод как

private static BiConsumer<Integer, Integer> 
        wrapperForLambda(BiConsumer<Integer, Integer> consumer) {   
    return (a, b) -> consumer.accept(a, b);
}

Когда вы используете raw BiConsumer, Java использует его в качестве целевого типа для лямбда-выражения (a, b) -> consumer.accept(a, b).Следствием этого является то, что предполагается, что параметры a и b имеют тип Object (необработанные типы, помните!), Что не будет работать с вашим consumer BiConsumer, который ожидает Integers.

Если предполагается, что это метод общего назначения, вы можете сделать его универсальным:

private static <T, U> BiConsumer<T, U> 
        wrapperForLambda(BiConsumer<T, U> consumer) {   
    return (a, b) -> consumer.accept(a, b);
}
0 голосов
/ 26 июня 2019

Вам не нужен метод wrappedForLambda, как правильно говорит @Eran.

Просто используйте лямбда-выражение напрямую.

public static void main(String[] args) {
    int[] numberArray = { 1, 2, 3, 4 };
    int key = 2;
    calc(numberArray, key, (a, b) -> System.out.println(a / b) );
    // Type Safety: The expression of Type BiConsumer needs unchecked conversion to conform to unchecked BiConsumer<Integer, Integer>
}

private static void calc(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
    for (int i : numberArray) {
        consumer.accept(i, key);
    }
}

Если по какой-то причине это не скомпилируется (старый JDK или старое затмение), приведите к Integer явно:

calc(numberArray, key, (Integer a, Integer b) -> System.out.println(a / b) );
0 голосов
/ 26 июня 2019

Вы можете использовать как

    return (a, b) -> consumer.accept((Integer) a, (Integer) b);

До Java 1.5 вы даже не могли этого сделать:

    int a;

    Object x = (Integer) a;

Компилятор жаловался бы, что a имеет примитивный тип данных,и, следовательно, не может быть приведен к объекту.

Начиная с Java 1.5, в Java появилась концепция автоматического бокса.Итак, все стало нормально:

    int a;

    Object x = (Integer) a;

Поскольку компилятор знает, как автоматически преобразовать из примитива int в упакованный тип Integer;и от Integer к объекту это, ну, не проблема.

Однако то, что вы пытаетесь сделать:

    int a;

    Object x = (int) a;

В основном говорит компилятору избегать упаковок.Вы явно указываете компилятору оставить a как int и поместить ссылку на этот int в Object.Компилятор не предназначен для такого случая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...