There is a keyword in java - final. It can be applied to classes, methods, variables (including method arguments). So final... - 1For a class, this means that the class cannot have subclasses, i.e. Inheritance is prohibited. This is useful when creating immutable(immutable) objects, for example a class Stringdeclared as final.
public final class String{
}

class SubString extends String{ //Compilation error
}
It should also be noted that the modifier cannot be applied to abstract classes (with the keyword abstract), finalbecause these are mutually exclusive concepts. For a method finalmeans that it cannot be overridden in subclasses. This is useful when we want the original implementation not to be overridden.
public class SuperClass{
    public final void printReport(){
        System.out.println("Report");
    }
}

class SubClass extends SuperClass{
    public void printReport(){  //Compilation error
        System.out.println("MyReport");
    }
}
For primitive type variables, this means that once assigned, the value cannot be changed. For reference variables, this means that once an object is assigned, the reference to that object cannot be changed. It is important! The link cannot be changed, but the state of the object can be changed. With java 8 the concept appeared - effectively final. It only applies to variables (including method arguments). The point is that despite the obvious absence of the keyword final, the value of the variable does not change after initialization. In other words, you can substitute a word for such a variable finalwithout a compilation error. effectively finalVariables can be used inside local classes ( Local Inner Classes), anonymous classes ( Anonymous Inner Classes), streams (Stream API).
public void someMethod(){
    // In the example below, both a and b are effectively final, since the values ​​are set once:
    int a = 1;
    int b;
    if (a == 2) b = 3;
    else b = 4;
    // c is NOT effectively final because value changes
    int c = 10;
    c++;

    Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
    Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
Now let's have a little interview. After all, the goal of taking the JavaRush course is to become a Java developer and get an interesting and well-paid job. So, let's begin.
  1. What can you say about an array when it is declared final?

  2. It is known that the class Stringis immutable, the class is declared final, the value of the string is stored in an array char, which is marked with the keyword final.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
Is it possible to replace the value of an object String(without changing the reference to the object)? These are real interview questions. And as practice shows, many answer them incorrectly. Understanding the use of the keyword final, especially for reference variables, is very important. While you're thinking, a quick digression to the JavaRush team. Please add a block in your text editor that allows you to hide the content, and when you click on it, show this content. Answers:
  1. Because an array is an object, which finalmeans that after assigning a reference to an object, it can no longer be changed, but the state of the object can be changed.

    final int[] array = {1,2,3,4,5};
    array[0] = 9;	//ok, because change the contents of the array - {9,2,3,4,5}
    array = new int[5]; //compile error
  2. Yes, you can. The key is to understand the use of the prickly word finalwith objects. Uses ReflectionAPI to replace the value.

import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        //Get the value field in the String class
        Field field = value.getClass().getDeclaredField("value");
        //Let's change it
        field.setAccessible(true);
        //Set new value
        field.set(value, "JavaRush".toCharArray());

        System.out.println(value);

        /* Вывод:
         * Old value
         * JavaRush
         */
    }
}
Please note that if we tried to change the final variable of a primitive type in this way, nothing would work. I suggest you convince yourself of this: create a Java class, for example, with final inta field and try to change its value via the Reflection API. Good luck to all!