1)
Один из ответов, о которых я не упомянул, состоит в том, что кадр стека для описываемого вами метода на самом деле может быть меньше. Каждый объявленный вами val
будет занимать слот в стеке JVM, однако всякий раз, когда вы используете def
полученное значение, оно будет использовано в первом выражении, в котором вы его используете. Даже если def
ссылается на что-то из среда, компилятор пройдет.
HotSpot должен оптимизировать обе эти вещи, как утверждают некоторые люди. См:
http://www.ibm.com/developerworks/library/j-jtp12214/
Поскольку внутренний метод компилируется в обычный закрытый метод за сценой, и он обычно очень мал, JIT-компилятор может решить встроить его, а затем оптимизировать. Это может сэкономить время, выделяя меньшие кадры стека (?), Или, имея меньше элементов в стеке, ускорить доступ к локальным переменным.
Но, возьмите это с (большим) зерном соли - я фактически не сделал обширных тестов, чтобы поддержать это утверждение.
2)
Кроме того, чтобы расширить действительный ответ Кевина, стабильный val
также предоставляет возможность использовать его с типами, зависящими от пути - то, что вы не можете сделать с def
, поскольку компилятор не проверяет его чистоту.
3)
По другой причине, вы можете захотеть использовать def
, см. Связанный вопрос, заданный не так давно:
Функциональная обработка потоков Scala без ошибок OutOfMemory
По сути, использование def
s для получения Streams
гарантирует, что не существует дополнительных ссылок на эти объекты, что важно для GC. Поскольку Stream
s в любом случае ленивы, затраты на их создание, вероятно, незначительны, даже если у вас есть несколько def
s.