изменение переменной из области лямбда-выражения в лямбда-Java - PullRequest
0 голосов
/ 13 июня 2018

У меня есть лямбда-функция, которая отправляется в другую функцию, я хочу изменить переменную, объявленную вне лямбда-области, в лямбду.

    WebElement  textArea ;
    BrowserToucher.clickOnWebElement(() -> {
        WebElement convPopupOrCard = findElementBy(driver, 
            conversationCardOrPopup);
        return textArea = findSubElementBy(driver, convPopupOrCard, 
            CardAndPopupTextArea);  
        }, driver);
    BrowserToucher.sendKeys(textArea, driver, text);

Мне нужно изменить 'textArea'var в labmda, поэтому я могу использовать его значение в последней строке.

Единственное решение, которое я нашел, - это сделать' textArea 'массивом размером 1. Но я не совсем понимаюпочему это работает.Буду рад, если кто-нибудь может объяснить это мне, пожалуйста.Спасибо !!

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Переменные внутри лямбда-выражения или любого анонимного внутреннего класса должны быть окончательными или эффективно конечными.

Это происходит потому, что эти переменные копируются в область лямбда-выражения.Если бы на них ссылались, а не на копировали, возникла бы проблема, когда переменная выходит из области действия своей зоны объявления, в то время как лямбда-область все еще выполняется (подумайте о потоках).

Определяя массив, вы работаетевокруг этой проблемы: вы принудительно ссылаетесь на значение с помощью эффективно окончательного массива (вы инициализируете массив один раз и никогда не меняете его).

Конечные и эффективно окончательные переменные можно безопасно скопировать, зная, что их значениене собирается меняться.

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

Вы можете сделать то же самое со списком или любой другой коллекцией.Это также будет работать с классом-оболочкой.

0 голосов
/ 13 июня 2018

Единственное решение, которое я нашел, - это сделать 'textArea' массивом размером 1, но я не совсем понимаю, почему он работает.

Это работает, потому что захваченныйСам массив является либо final , либо эффективно final (любая переменная, значение которой не изменяется).

Пока захваченная переменная конечная или фактически окончательная , изменение содержимого массива полностью нормально и допустимо.

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

0 голосов
/ 13 июня 2018

Если я правильно понимаю вашу проблему, решение будет не таким сложным, если вы помните, что лямбды - это просто функции, но без имен, так что вы можете передать любой аргумент в скобках, как вы это делаете с «обычными» методами java.

Единственное решение, которое я нашел, - это сделать 'textArea' массивом размером 1. Но я не совсем понимаю, почему он работает.

Этоуже очень хорошо описано в одной из тем переполнения стека, касающихся ссылки на Java.Пожалуйста, ознакомьтесь с ним, и вы поймете это навсегда, и Мэйби придумала другое решение для вашей проблемы:)

Является ли Java "передачей по ссылке" или "передачей по ссылке"значение "

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