CodeGym /Java Blog /Keywords in Java /Let's Talk About Final Keyword In Java
Oleksandr Miadelets
Head of Developers Team at CodeGym

Let's Talk About Final Keyword In Java

Published in the Keywords in Java group
Java has this keyword — final. It can be applied to classes, methods, variables (including method parameters). For a class, the final keyword means that the class cannot have subclasses, i.e. inheritance is forbidden... This is useful when creating immutable (unchangeable) objects. For example, the String class is declared as final.

    public final class String {
    class SubString extends String { // Compilation error
I should also note that the final modifier cannot be applied to abstract classes (those with the keyword abstract), because these are mutually exclusive concepts. For a final method, the modifier means that the method cannot be overridden in subclasses. This is useful when we want to prevent the alteration of the original implementation.

    public class SuperClass {
        public final void printReport() {

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
For variables of a primitive type, the final keyword means that the value, once assigned, cannot be changed. For reference variables, it means that after an object is assigned, you cannot change the reference to that object. This is important! The reference cannot be changed, but the object's state can be changed. Java 8 introduced a new concept: effectively final. It applies only to variables (including method parameters). The bottom line is that despite the clear absence of the final keyword, the variable's value does not change after initialization. In other words, the final keyword can be applied to such a variable without a compilation error. Effectively final variables can be used inside local classes (local inner classes), anonymous classes (anonymous inner classes), and streams (Stream API).

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            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 completing the CodeGym course is to become a Java developer and find an interesting and well-paid job. So, let's begin.
  1. What can we say about an array that is declared final?

  2. We know that the String class is immutable: the class is declared final. A string value is stored in a char array that is marked with the keyword final.

public final class String
    implements, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

Can we replace a String object's value (without changing the reference to the object)? These are real interview questions. And practice shows that many candidates do not answer them correctly. Understanding how the final keyword is used, especially for reference variables, is very important. As you contemplate this, I'll make a small request to the CodeGym team. Please give the text editor the ability to add a block whose content can be shown/hidden when you click on it. Answers:
  1. An array is an object, so the final keyword means that once a reference to the array is assigned, the reference cannot be changed. That said, you can change the state of the object.

            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
  2. Yes, we can. The main thing is to understand what the thorny final keyword means when used with objects. The Reflection API can be used to replace values.

import java.lang.reflect.Field;

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

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        // Set a new value
        field.set(value, "CodeGym".toCharArray());


        /* Output:
         * Old value
         * CodeGym
Please note that if we had tried to change the final variable of a primitive type in this way, then nothing would have happened. I suggest that you convince yourself: create a Java class, for example, with a final int field and try to change its value using the Reflection API. Good luck to all!
Comments (3)
Naughtless Level 41, Olympus Mons, Mars
8 March 2022
So, the solution in using Reflection API to change a String's value is completely outdated. It no longer works due to a 'Platform Module System' being implemented since Java 9. This effectively renders the Reflection API a very weak shadow of it's former self, as it can no longer break into encapsulation. Now you can only use Field.setAccessible() on public elements, which makes Reflection quite redundant when it comes to accessing elements protected by encapsulation.
Dan Level 26, Clarksville, United States Expert
7 December 2021
Note: When I paste the final 22 line code and try to run it on IntelliJ, I get an "Inaccessible Object Exception". I believe that this is due to the "Java Platform Module System" Introduced in Java 9. It causes an Exception unless the type is public or the owning package is exported. There are a few ways around it, from what I understand. If you're interested in more reading, There are some great answers on StackOverflow if you search up "Inaccessible Object Exception reflection java". Happy Coding!
9 January 2020
crystal clear!