There is a keyword in java -
final
. It can be applied to classes, methods, variables (including method arguments). For 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 String
declared 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
), final
because these are mutually exclusive concepts. For a method final
means 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 final
without a compilation error. effectively final
Variables 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.
-
What can you say about an array when it is declared
final
? -
It is known that the class
String
isimmutable
, the class is declaredfinal
, the value of the string is stored in an arraychar
, which is marked with the keywordfinal
.
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:
-
Because an array is an object, which
final
means 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
-
Yes, you can. The key is to understand the use of the prickly word
final
with 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 int
a field and try to change its value via the Reflection API. Good luck to all!
GO TO FULL VERSION