final поля хорошо использовать для неизменяемых объектов. Т.е. если некое поле в объекте не меняется — это хороший кандидат на final.
еще final отлично работает в многопоточной среде, если использовать функциональный подход. если несколько потоков что-то вычисляют, то правильней будет создать новый неизменный объект из старого, чем менять старый и писать синхронизацию.
также я иногда объявляю локальные переменные как final — например, если для удобства значение этой переменной достается из некой сложной конструкции, а используется часто, типа currentTask.getAssigner().getEmail().toUpperCase() — каждый раз такое писать утомляет, а так в переменную записал и код гораздо чище станет. final в данном примере мне служит маркером, ну и чтобы случайно туда ничего не записать.