# Make Fields And Variables Final

# Description

This rule declares private fields and local variables final, if they are effectively final.

The criteria for being effectively final are as follows:

  • The variable or field is not assigned after its initialisation
  • Initialisation of non-static fields:
    • At the declaration OR
    • In a non-static class initialiser OR
    • In ALL constructors of the class
  • Initialisation of static fields:
    • At the declaration OR
    • In a static initialiser

# Benefits

Readability and maintainability of code is improved and accidental reassignments are prevented for affected fields and variables.

# Tags

# Code Changes

# Assignments

Pre

public class MakeFinal {
    private String nonStaticField = "nonStaticField";
    private String nonStaticFieldEffectivelyFinal ="nonStaticFieldEffectivelyFinal";
    private static String staticField = "staticField";
    private static String staticFieldEffectivelyFinal = "staticFieldEffectivelyFinal";

    public void localVariables() {
        int i = 0;
        int j = 0;
        System.out.println(i);
        System.out.println(j++);
    }

    public void nonStaticFields() {
        nonStaticField += "Altered";
        System.out.println(nonStaticField);
        System.out.println(nonStaticFieldEffectivelyFinal);
    }

    public static void staticFields() {
        staticField = staticField + "Altered";
        System.out.println(staticField);
        System.out.println(staticFieldEffectivelyFinal);
    }
}

Post

public class MakeFinal {
    private String nonStaticField ="nonStaticField";
    private final String nonStaticFieldEffectivelyFinal ="nonStaticFieldEffectivelyFinal";
    private static String staticField = "staticField";
    private static final String staticFieldEffectivelyFinal = "staticFieldEffectivelyFinal";

    public void localVariables() {
        final int i = 0;
        int j = 0;
        System.out.println(i);
        System.out.println(j++);
    }

    public void nonStaticFields() {
        nonStaticField += "Altered";
        System.out.println(nonStaticField);
        System.out.println(nonStaticFieldEffectivelyFinal);
    }

    public static void staticFields() {
        staticField = staticField + "Altered";
        System.out.println(staticField);
        System.out.println(staticFieldEffectivelyFinal);
    }
}

# static Field Initialisation

Pre

public class MakeFinal {
    private static String initInDeclaration = "initInDeclaration";
    private static String initInStaticInitialiser;
    private static String initInDeclarationAndStaticInitialiser = "initInDeclarationAndStaticInitialiser";
    private static String noInit;

    static {
        initInStaticInitialiser = "initInStaticInitialiser";
        initInDeclarationAndStaticInitialiser = "initInDeclarationAndStaticInitialiser";
    }

    ...
}

Post

public class MakeFinal {
    private static final String initInDeclaration = "initInDeclaration";
    private static final String initInStaticInitialiser;
    private static String initInDeclarationAndStaticInitialiser = "initInDeclarationAndStaticInitialiser";
    private static String noInit;

    static {
        initInStaticInitialiser = "initInStaticInitialiser";
        initInDeclarationAndStaticInitialiser = "initInDeclarationAndStaticInitialiser";
    }

    ...
}

# Non-static Field Initialisation

Pre

public class MakeFinal {
    private String initInDeclaration = "initInDeclaration";
    private String initInClassInitialiser;
    private String initInAllConstructors;
    private String initInOneConstructorOnly;
    private String initInDeclarationAndClassInitialiser = "initInDeclarationAndClassInitialiser";
    private String noInit;

    {
        initInClassInitialiser = "initInClassInitialiser";
        initInDeclarationAndClassInitialiser = "initInDeclarationAndClassInitialiser";
    }

    public MakeFinal()  {
        initInAllConstructors = "initInAllConstructors";
        initInOneConstructorOnly = "initInOneConstructorOnly";
    }

    public MakeFinal(String arg1) {
        initInAllConstructors = "initInAllConstructors";
    }

    ...
}

Post

public class MakeFinal {
    private final String initInDeclaration = "initInDeclaration";
    private final String initInClassInitialiser;
    private final String initInAllConstructors;
    private String initInOneConstructorOnly;
    private String initInDeclarationAndClassInitialiser = "initInDeclarationAndClassInitialiser";
    private String noInit;

    {
        initInClassInitialiser = "initInClassInitialiser";
        initInDeclarationAndClassInitialiser = "initInDeclarationAndClassInitialiser";
    }

    public MakeFinal()  {
        initInAllConstructors = "initInAllConstructors";
        initInOneConstructorOnly = "initInOneConstructorOnly";
    }

    public MakeFinal(String arg1) {
        initInAllConstructors = "initInAllConstructors";
    }

    ...
}

# Limitations

This rule only affects private fields and local variables at the moment. public, protected or package-private fields as well as method parameters are not considered yet.

You Want To Have Those Changes Done Automatically?

The automatic application of this rule is supported in the following jSparrow version:

# Properties

Property Value
Rule ID MakeFieldsAndVariablesFinal
First seen in jSparrow version 3.12.0
Minimum Java version 1.1
Remediation cost 5 min