I noticed that professional developers often declare class fields in Java as final, for example:

@Component public class LinkResolver implements GraphQLResolver<Link> { private final UserRepository userRepository; public LinkResolver(UserRepository userRepository) { this.userRepository = userRepository; } public User postedBy(Link link) { if (link.getUserId() == null) { return null; } return userRepository.findById(link.getUserId()); } } 

What is it done for? I saw how not only the services and repositories fields are declared in the final project, but also the data class fields. Tell us more about this, please.

  • four
    So that you can initialize a variable only once, for example, only in the constructor - gil9red

3 answers 3

Many bukav: By default, set maximum limits. Removing the restriction (final) from the field makes sense only if there is a reason for it (the field changes).

final marks fields that are initialized only once. It is technically not necessary to mark such a field as final , but if this is not done, then:

  • the possibility of error will remain: the developer will be sealed and reassign the value;
  • When reading the code, questions will arise: “Where does this field change? And how will this affect the rest of the code? ” The final modifier tells the developer that unnecessary scripts should not be considered.

In general, a significant part of programming is the placement of restrictions. The fewer operations you can perform with the code — the easier it is to reason about it — the easier it is to check its correctness. Therefore, developers are trying to set the most stringent restrictions for fields / variables to reduce the number of possible scenarios for their use.

For a similar reason, fields that are not used outside the class are declared private . The field with default access will leave unnecessary usage scenarios and, together with them, room for errors and questions (“What class does it go to and why?”).

Many IDE and code analysis tools (for example, PMD ) track fields and variables that can be marked as final and issue appropriate warnings.

In practice, fields, as an important part of classes, wherever possible, are marked as final. On local variables and arguments of methods, they usually “save”, since their life expectancy is shorter and the risk of side effects is less. For them, on the contrary, they use final only where it is clearly necessary (use in anonymous classes). For example, in your code, the constructor ( userRepository ) and method ( link ) arguments might be marked as final , but not marked for simplicity of the code.

    1. Conveniently purely visually. If you see that the variable is final , then you know for sure that it will not change.
    2. No final way, if you are going to use a local variable in anonymous classes / closures.
    3. final is a hint to the compiler. If he sees the final fields, he can make certain code optimizations.
    • And final, applied to fields, can have any value at inheritance? - typemoon
    • @typemoon no principled. Fields still remain unchanged. - Suvitruf
    • One cunning lies in the answer, some newcomers confuse final with immutability ... - Stranger in the Q
    • 2
      4. final-fields are safely published in a multi-threaded environment - Pavel Mayorov
    • @StrangerintheQ you can write more about reflection) - Suvitruf

    The final modifier in the margin indicates that this field is final and cannot be changed.
    Often, constants are declared final in Java , whose value fields are immutable.
    Also final it is possible to declare the whole classes, or methods.