Cannot refer to a non-final variable inside an inner class defined in a different method
Невозможно ссылаться на неокончательную переменную внутри внутреннего класса, определенного другим методом
Отредактировано: мне нужно изменить значения нескольких переменных, поскольку они выполняются несколько раз по таймеру. Мне нужно постоянно обновлять значения с каждой итерацией по таймеру. Я не могу установить значения в final, поскольку это помешает мне обновить значения, однако я получаю ошибку, которую я описываю в начальном вопросе ниже:
Я ранее написал то, что приведено ниже:
Я получаю сообщение об ошибке "не удается ссылаться на неокончательную переменную внутри внутреннего класса, определенного другим методом".
Это происходит для дважды вызываемой price и Price, называемой priceObject . Вы знаете, почему у меня возникает эта проблема. Я не понимаю, зачем мне нужно иметь окончательное объявление. Также, если вы видите, что я пытаюсь сделать, что мне нужно сделать, чтобы обойти эту проблему.
Java не поддерживает истинные замыкания, хотя использование анонимного класса, подобного тому, который вы используете здесь (new TimerTask() { ... }), выглядит как своего рода замыкание.
редактировать - Смотрите комментарии ниже - следующее неверное объяснение, как указывает KeeperOfTheSoul.
Вот почему это не работает:
Переменные lastPrice и price являются локальными переменными в методе main() . Объект, который вы создаете с помощью анонимного класса, может сохраняться до тех пор, пока main() метод не вернет результат.
Когда main() метод возвращает значения, локальные переменные (такие как lastPrice и price) будут удалены из стека, поэтому после main() возврата они больше не будут существовать.
Но анонимный объект класса ссылается на эти переменные. Все пойдет ужасно неправильно, если анонимный объект класса попытается получить доступ к переменным после их очистки.
Создавая lastPrice и pricefinal, они на самом деле больше не переменные, а константы. Затем компилятор может просто заменить использование lastPrice и price в анонимном классе значениями констант (во время компиляции, конечно), и у вас больше не будет проблем с доступом к несуществующим переменным.
Другие языки программирования, которые поддерживают замыкания, делают это, обрабатывая эти переменные особым образом - следя за тем, чтобы они не уничтожались при завершении метода, чтобы замыкание все еще могло получить доступ к переменным.
timer.scheduleAtFixedRate(newTimerTask() { // Variables as member variables instead of local variables in main() privatedoublelastPrice=0; privatePricepriceObject=newPrice(); privatedoubleprice=0;
Чтобы избежать странных побочных эффектов с замыканиями в java, переменные, на которые ссылается анонимный делегат, должны быть помечены как final, поэтому для ссылки на lastPrice и price в задаче timer они должны быть помечены как final.
Очевидно, что у вас это не сработает, потому что вы хотите их изменить, в этом случае вам следует рассмотреть возможность их инкапсуляции внутри класса.
Вы можете получить доступ к конечным переменным только из содержащего их класса при использовании анонимного класса. Поэтому вам нужно объявить используемые переменные final (что для вас не вариант, поскольку вы меняете lastPrice и price), или не использовать анонимный класс.
Итак, ваши варианты - создать реальный внутренний класс, в который вы можете передавать переменные и использовать их обычным способом
или:
Есть быстрый (и, на мой взгляд, уродливый) способ взломать ваши переменные lastPrice и price, который заключается в объявлении их следующим образом
finaldouble lastPrice[1]; finaldouble price[1];
и в вашем анонимном классе вы можете установить значение следующим образом
Кажется, что, вероятно, вы могли бы создать дизайн получше, но идея в том, что вы могли бы сгруппировать обновленные переменные внутри ссылки на класс, которая не меняется.