Specifier final. Immutable (constant) data, methods, classes. Empty constants. Static immutable data. Inline methods

Specifier final. Immutable (constant) data, methods, classes. Empty constants. Static immutable data. Inline methods


Contents


1. What is the purpose of using the final keyword in Java programs?

The final keyword is intended to declare immutable data, methods and classes. Immutable data, methods or classes cannot change their value or program code during the program execution.

If the declaration of a variable uses the keyword final, then this variable automatically becomes a constant. Attempting to change the value of the final-constant will result in an error.

2. In which java programming language elements can the final keyword be used?

The final keyword can be applied to such elements of the language as:

  • data (constants, variables);
  • methods;
  • classes.

3. What are some ways you can initialize immutable data in a class that are declared with the keyword final?

There are two ways to set the initial value of unchanged data:

  • using the direct assignment (=) of a value when declaring a final-data field of a class;
  • using a class constructor. This method is only suitable for non-static unchanged data. First, a class field with the keyword final is declared in the class. This field is called a blank constant (blank field). Then this blank constant is necessarily initialized by a value in the class constructor. The number of overloaded constructors that initialize blank constants can be any.

4. What are the differences between immutable and mutable data? What are the features of immutable data in the class?

There are two differences between immutable data and mutable data:

  • immutable data is declared with the keyword final;
  • immutable data is given a value only once when it is declared or using a class constructor. Data that changes can receive different values as much as necessary. That is, immutable data cannot be used on the left side of the assignment operator = (as opposed to data that changes).

5. An example that demonstrates the use of the final keyword with single data

The class ConstData is declared, containing immutable data in the form of variables a, c. When trying to change the values of a, c compiler will generate an error. The final keyword also applies to static variables (variable c). Below is the code for the class ConstData.

// class that contains immutable data
class ConstData {
  public final int a=32; // the variable a has the constant value
  public int b=50; // variable, whose value can be changed
  public final static double c=3.85; // the value of the static member c is a constant

  // a method that changes the value of b
  public void Change() {
    // a = 45; - error, you can not change the value of final-variable
    b = 120; // this works because b is declared without final
    //ConstData.c = 320.53; - error, variable c is declared as final
  }
}

The following program code demonstrates the use of the ConstData class.

// use of object of class ConstData
ConstData fd = new ConstData();
fd.Change();

int t = fd.b; // t = 120
t = fd.a; // t = 32, final data can be read only

// you cannot change the value of a static member of ConstData.c
// ConstData.c = 230.55; - error!
double d = ConstData.c; // d = 3.85

6. How to initialize the final-data using the constructor? Example

Immutable static data that was declared with the final keyword can be initialized using a constructor, provided that no value has been assigned to this data when it is declared in the class.

For example. The SetConstData class is declared, in which different kinds of data are declared:

  • ordinary data (variables) whose values can be changed;
  • immutable non-static data that is declared using the keyword final;
  • immutable static data that were declared with the combination of the static and final keywords.

The class also contains the declaration of three constructors, which initialize those immutable data that did not initialize during the declaration.

The class implementation is as follows:

// class that contains various kinds of data
class SetConstData {
  public final int a; // the constant a must be initialized in the constructor
  public int b=50; // a variable whose value can be changed many times
  public final static double c=0; // the value of the static member c is initialized upon declaration
  public final char d = 'Z'; // the constant d is already initialized, it cannot be initialized in the constructor
  public final int e = 25; // value is assigned when declaring
  public final boolean f; // must be assigned a value in the constructor

  // a constructor that changes the values of a, b, f
  SetConstData() {
    a = 100; // you can set only once the value of the final variable a
    b = 200;

    // SetConstData.c = 300.0;

    // it is forbidden to initialize the final variable d, since it has already been initialized
    // d = 'F'; - error

    // it is necessary to initialize the final-constant
    f = true;
  }

  // second constructor that initializes immutable data
  SetConstData(int _a, int _b, boolean _f) {
    // you can initialize only immutable data a, f
    a = _a;
    b = _b;
    f = _f;
  }

  // third constructor that initializes immutable data
  SetConstData(int _a, boolean _f) {
    a = _a;
    f = _f;
  }

  // method that changes the value of b
  public void Change() {
    // a = 45; - error, you cannot change the value of final-data
    b = 120; // it works, because b is declared without final
    //FinalData.c = 320.53; - error, the variable c is declared as final
  }
}

In the above code, the immutable data (fields) a and f are empty constants that must be initialized in the class constructor.

The use of the SetConstData class can be as follows:

// Using different types of constructors to initialize immutable data
//SetConstData.c = 32309; - no final-static data can be assigned
double d = SetConstData.c; // d = 0.0

// create an instance of the SetConstData class using the constructor without parameters
SetConstData sd = new SetConstData();
boolean f = sd.f; // f = true
int t = sd.a; // t = 100
t = sd.e; // t = 25

// Create an instance of SetConstData using a constructor with 3 parameters
SetConstData sd2 = new SetConstData(15,35,false); // immutable data are initialized
t = sd2.a; // t = 15
t = sd2.b; // t = 35
f = sd2.f; // f = false

// Create an instance of SetConstData using a constructor with 2 parameters
SetConstData sd3 = new SetConstData(9, true);
t = sd3.a; // t = 9
f = sd3.f; // f = true

7. What happens if the data declared with the final keyword does not initialize to values in the class?

If final-data is declared in a class, they must be initialized once with a certain value. If you do not initialize the final-data by any of the known ways, the compiler will generate a warning about a possible error.

For example. In the class below, a class final-field is declared.

// initialization
class InitFinalData {
  final double pi = 3.1415;
  final int d; // the value of d is not initialized - maybe an error
}

Java compiler skips this description with a warning

The blank final field d may not have been initialized

8. What are the features of immutable (constant) data that are declared as static?

In comparison with non-static, for static unchanged data the following features can be distinguished:

  • static immutable data is declared with the combination of the keywords final static;
  • the value of the static immutable data member is initialized upon declaration. You cannot initialize the value of a static immutable data member in a class constructor;
  • a static immutable data member of a class is assigned a value only once per declaration.



9. What are blank constants (fields)?

Blank constants are class fields that are declared with the final keyword but which are not initialized by an initial value (which was not assigned an initial value). The value of an empty constant must be initialized in the class constructor.

10. Can static data fields of a class be a blank constant?

No, they cannot. Static class data fields are declared with the static keyword. During the declaration, they should immediately be assigned a value, for example

final static int si = 25;
final static double pi = 3.1415;
final static char c = '0';
final static int t; // this may be an error, uninitialized value of t

11. What are immutable (constant) arguments? Example

Immutable (constant) arguments are the arguments that are declared with the keyword final when passed to a method. Immutable arguments are declared when the method is implemented. The value of the constant argument in the method cannot be changed. If you try to change the value of the constant argument, a compilation error will be occured.

For example. The FinalArguments class is declared, containing two methods that get a final arguments. The first Power() method gets two constant (final) parameters x, y. The method raises x to the power of y. The second method, Sqr(), returns the square of the number, which is the input parameter x, which is declared as constant (final).

The code for the FinalArguments class is as follows

class FinalArguments {
  // raises x to the power of y
  public double Power(final int x, final int y) {
    double res = 1.0;
    for (int i=0; i<y; i++)
      res = res * x;
    return res;
  }

  // returns the square of a number
  public double Sqr(final double x) {
    return x*x;
  }
}

The following is the use of the FinalArguments class methods

// use of methods of class FinalArguments
FinalArguments fa = new FinalArguments();
double d;
d = fa.Power(8, 5); // d = 32768.0
d = fa.Sqr(5); // d = 25.0

If the Sqr() method in the FinalArguments class rewrite, for example, as follows

public double Sqr(final double x) {
  x = x*x; // this is an error because the x value is changed
  return x;
}

the compiler will generate an error

The final local variable x cannot be assigned

This happens because the Sqr() method attempts to change the value of the constant argument x.

12. Why use immutable (constant) methods?

In the Java programming language, the keyword final can be placed before a method declaration. This method is called the immutable method.

The immutable method is declared in the following cases:

  • if you want to block the method in inherited classes. That is, inherited classes cannot change the content of a method declared with the keyword final;
  • if you need to recommend to the compiler that the method call is built-in (inline). However, this is only a recommendation. The compiler itself determines whether to use the standard mechanism to insert a method into the code (put the arguments on the stack, handle the execution of the method, pull the arguments from the stack, handle the result) or directly insert the method code into the body of the caller.

13. What are inline methods?

In most programming languages, the usual method call from some code requires the following sequence of required operations:

  • put arguments to the stack (if the method has parameters);
  • go to the body of the method;
  • execute the code (body) of the method;
  • return from method;
  • remove arguments from the stack;
  • process the value returned from the method.

Inline methods are methods whose body is directly inserted into the program code of the calling program (method). In this case, there are no extra steps when calling a method: putting arguments on the stack, conversion and return from the method. The absence of extra steps increases the speed of execution of the called method. That is, increases the overall speed of the program that caused the method.

However, if the body of the inline method is quite large (contains a lot of code), then this leads to an excessive increase in the program that caused it.

14. Example of declaring and using immutable (constant) methods

Class A is set, which is basic for class B. In class A are declared

  • one internal variable a;
  • two constant methods Set() and Get(). These methods are not allowed to be overridden in the inherited class B
  • two common methods Set() and Get(), which can be overridden in the inherited class.

The declaration of classes A and B is as follows:

// class A - base class
class A {
  public int a;

  // methods that cannot be overridden in inherited classes
  final void Set(int _a) { a = _a;   }
  final int Get() { return a; }

  // methods that are allowed to override in inherited classes
  void SetA(int _a) { a = _a; }
  int GetA() { return a; }
}

// class B inherits (extends) the capabilities of class A
class B extends A {
  public int b;

  // class B methods override class A methods
  void SetA(int _a) { a = _a; }
  int GetA() { return a; }

  // It is forbidden to declare the Set() and Get() methods in class B
  // void Set(int _a) { a = _a; }
  // int Get() { return a; }
}

The use of instances of classes A and B may be, for example, the following

// the us of objects of classes A and B
A objA = new A();
objA.Set(5); // objA.a = 5
int t = objA.Get(); // t = 5
t = objA.GetA(); // t = 5
B objB = new B();
objB.Set(12);
t = objB.Get(); // t = 12
objB.SetA(54);
t = obj.Get(); // t = 54
t = obj.Get(); // t = 54

If in class B try to declare the methods Set() and Get() as follows

class B extends A {
  ...

  // It is forbidden to declare the Set() and Get() methods in class B
  void Set(int _a) { a = _a; }
  int Get() { return a; }
}

then the compiler will generate an error

Cannot override the final method from A

15. What are the features of using final and private qualifiers for methods?

The private specifier makes the class method invisible. That is, inherited classes cannot redefine it or change it in the same way as when declaring a final method. This means that combining these specifiers creates redundancy in the declaration. If a method is declared as private, then it is inappropriate to add the final specifier to its declaration, since this will not change anything.

If a private method with a name, for example ABC(), is declared in the class, then in the inherited class you can create a method with the same name ABC().However, the ABC() method of the inherited class has nothing to do with the ABC() method of the base class. The ABC() method of the inherited class does not override the ABC() method of the base class – these are methods of different classes in which the name just matches.

16. Can an immutable method be declared as static?

Yes, it can. In this case, calling a static immutable method from a class is the same as a regular static method (without the keyword final).

17. What are immutable (constant) classes? When is it advisable to use immutable classes? Example

The immutable class is a class that cannot be used as a base for heredity. A constant class cannot be inherited by another class. Before declaring an immutable class, the final specifier is used, as shown below.

// immutable class
final class ClassName {
  // body of class
  // ...
}

Immutable classes are used in cases when it is necessary to prohibit any inheritance of this class for security reasons. The structure of an unchanged class remains constant. All methods of an immutable class are also unchanged regardless of the presence (absence) of the final specifier.

Example. Let the declaration of an immutable class A be given:

// immutable class A
final class A {
  int a;
}

After such a declaration, you cannot declare a class that inherits (extends) class A. If you try to do this, the compiler will generate an error.

The next time you try to declare a class B that inherits (extends) the capabilities of class A

// class A cannot be inherited
class B extends A {
  int b;
}

then the compiler generates an error:

The type B cannot subclass the final class A

The use of the final class A in another program code may be as follows:

// declare an object of class A
A objA = new A();
objA.a = 32;
int t = objA.a; // t = 32


Related topics