C'è una parola chiave in Java -
final
. Può essere applicato a classi, metodi, variabili (compresi gli argomenti del metodo). Per una classe, ciò significa che la classe non può avere sottoclassi, ad es. L'eredità è vietata. Ciò è utile quando si creano immutable
oggetti (immutabili), ad esempio una classe String
dichiarata come final
.
public final class String{
}
class SubString extends String{ //Compilation error
}
Va inoltre notato che il modificatore non può essere applicato a classi astratte (con la parola chiave abstract
), final
perché questi sono concetti che si escludono a vicenda. Per un metodo final
significa che non può essere sovrascritto nelle sottoclassi. Ciò è utile quando vogliamo che l'implementazione originale non venga sovrascritta.
public class SuperClass{
public final void printReport(){
System.out.println("Report");
}
}
class SubClass extends SuperClass{
public void printReport(){ //Compilation error
System.out.println("MyReport");
}
}
Per le variabili di tipo primitivo, ciò significa che una volta assegnato, il valore non può essere modificato. Per le variabili di riferimento, ciò significa che una volta assegnato un oggetto, il riferimento a quell'oggetto non può essere modificato. È importante! Il collegamento non può essere modificato, ma è possibile modificare lo stato dell'oggetto. Con Java 8 è apparso il concetto: effectively final
. Si applica solo alle variabili (inclusi gli argomenti del metodo). Il punto è che nonostante l'ovvia assenza della parola chiave final
, il valore della variabile non cambia dopo l'inizializzazione. In altre parole, è possibile sostituire una parola con tale variabile final
senza che si verifichi un errore di compilazione. effectively final
Le variabili possono essere utilizzate all'interno di classi locali ( Local Inner Classes
), classi anonime ( Anonymous Inner Classes
), flussi (API Stream).
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
}
Adesso facciamo una piccola intervista. Dopotutto, l'obiettivo di seguire il corso JavaRush è diventare uno sviluppatore Java e ottenere un lavoro interessante e ben pagato. Quindi, cominciamo.
-
Cosa puoi dire di un array quando viene dichiarato
final
? -
È noto che la classe
String
èimmutable
, la classe viene dichiaratafinal
, il valore della stringa viene memorizzato in un arraychar
contrassegnato con la parola chiavefinal
.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
È possibile sostituire il valore di un oggetto String
(senza modificare il riferimento all'oggetto)? Queste sono vere domande da intervista. E come dimostra la pratica, molti rispondono in modo errato. Comprendere l'uso della parola chiave final
, soprattutto per le variabili di riferimento, è molto importante. Mentre stai pensando, una breve digressione sul team JavaRush. Aggiungi un blocco nel tuo editor di testo che ti consenta di nascondere il contenuto e, quando fai clic su di esso, mostra questo contenuto. Risposte:
-
Perché un array è un oggetto, il che
final
significa che dopo aver assegnato un riferimento a un oggetto, non è più possibile modificarlo, ma è possibile modificare lo stato dell'oggetto.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
-
Si, puoi. La chiave è comprendere l'uso della parola pungente
final
con gli oggetti. Utilizza ReflectionAPI per sostituire il valore.
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
*/
}
}
Tieni presente che se provassimo a modificare la variabile finale di un tipo primitivo in questo modo, non funzionerebbe nulla. Ti suggerisco di convincerti di questo: crea una classe Java, ad esempio, con final int
un campo e prova a cambiarne il valore tramite la Reflection API. Buona fortuna a tutti!
GO TO FULL VERSION