Как отмечено в комментариях, часть этого становится неактуальной в Java 8, где это final
может быть неявным. Однако в анонимном внутреннем классе или лямбда-выражении можно использовать только эффективно окончательную переменную.
В основном это связано с тем, как Java управляет замыканиями .
Когда вы создаете экземпляр анонимного внутреннего класса, любые переменные, которые используются в этом классе, копируются в свои значения через автоматически сгенерированный конструктор. Это избавляет компилятор от необходимости автоматически генерировать различные дополнительные типы для хранения логического состояния «локальных переменных», как, например, это делает компилятор C # ... (Когда C # захватывает переменную в анонимной функции, он действительно захватывает переменную - Закрытие может обновить переменную таким образом, который виден основной частью метода, и наоборот.)
Поскольку значение было скопировано в экземпляр анонимного внутреннего класса, выглядело бы странно, если бы переменная могла быть изменена остальной частью метода - у вас мог бы быть код, который, казалось, работал с устаревшей переменной ( потому что именно так и происходит ... вы работаете с копией, сделанной в другое время). Аналогично, если бы вы могли вносить изменения в анонимном внутреннем классе, разработчики могли бы ожидать, что эти изменения будут видны в теле включающего метода.
Если сделать окончательную переменную, все эти возможности будут удалены - поскольку значение не может быть изменено вообще, вам не нужно беспокоиться о том, будут ли такие изменения видны. Единственный способ позволить методу и анонимному внутреннему классу видеть изменения друг друга - это использовать изменяемый тип некоторого описания. Это может быть сам класс включения, массив, изменяемый тип-обертка ... что-нибудь в этом роде. По сути, это немного похоже на обмен данными между одним методом и другим: изменения, внесенные в параметры одного метода, не отображаются его вызывающей стороной, но видны изменения, внесенные в объекты, на которые ссылаются параметры.
Если вас интересует более подробное сравнение между замыканиями Java и C #, у меня есть статья, которая углубляется в это. Я хотел сосредоточиться на стороне Java в этом ответе :)