Use final liberally

Use the final keyword liberally to communicate your intent.

The final keyword has more than one meaning:

In the last case, "value" for primitives is understood in the usual sense, while "value" for objects means the object's identity, not its state. Once the identity of a final object reference is set, it can still change its state, but not its identity (that is, you can't re-point the object reference to some other object).

Declaring primitive fields as final automatically ensures thread-safety for that field.

Some habitually declare parameters as final, since this is almost always the desired behaviour. Others find this verbose, and of little real benefit.

Consistently using final with local variables (when appropriate) can be useful as well. It brings attention to the non-final local variables, which usually have more logic associated with them (for example, result variables, accumulators, loop variables). Many find this verbose. A reasonable approach is to occasionally use final for local variables, but only if there is some unusual condition, whereby making final explicit can call attention to at least one non-final local variable in the method; this serves to quickly distinguish the non-final local variables from the others.

Using final:

Example
import java.util.*;

/** This class cannot be extended, since it's final. */
public final class Boat {

  public Boat(final String name, final int length, final Date dateManufactured){
    this.name = name;
    this.length = length;
    //make a defensive copy of the date
    this.dateManufactured = new Date(dateManufactured.getTime());

    //does not compile, since the items are final:
    //aDateManufactured = null;
    //aLength = 0;
  }

  /** Cannot be overridden, since the class itself is final. */
  public void setDate(final Date newDate){
    //even though the field is final, its state can change:
    dateManufactured.setTime(newDate.getTime());

    //does not compile, since field is final:
    //fDateManufactured = aNewDate;
  }

  /** Return the highest race score. */
  public Integer bestRaceScore(){
    //the result reference can't be final, since it can be 
    //re-pointed to different objects
    Integer result = Integer.valueOf(0); 
    //final Integer result = Integer.valueOf(0); //doesn't compile
    
    //this example is artificial, since raceScores could be 
    //referenced directly here...
    final List<Integer> scores = raceScores;
    for(Integer score : scores){
      if (score > result){
        result = score; //re-point to the max value
      }
    }
    return result;
  }
  
  //..elided

  // PRIVATE
  private final String name;
  private final int length;
  private List<Integer> raceScores = new ArrayList<>();
  /** 
   New code should almost always use java.time, not java.util.Date.
   java.util.Date is used here simply as an example of a mutable field.
  */ 
  private final Date dateManufactured;
}  

See Also :
Immutable objects
Designing for subclassing
Overridable methods need special care
Remember styles of inheritance