Es gibt ein Schlüsselwort in Java -
final
. Es kann auf Klassen, Methoden und Variablen (einschließlich Methodenargumente) angewendet werden. Für eine Klasse bedeutet dies, dass die Klasse keine Unterklassen haben kann, d. h. Eine Vererbung ist verboten. Dies ist nützlich, wenn Sie immutable
(unveränderliche) Objekte erstellen, beispielsweise eine Klasse, String
die als deklariert ist final
.
public final class String{
}
class SubString extends String{ //Kompilierungsfehler
}
Es ist auch zu beachten, dass der Modifikator nicht auf abstrakte Klassen (mit dem Schlüsselwort abstract
) angewendet werden kann, final
weil Dies sind sich gegenseitig ausschließende Konzepte. Denn eine Methode final
bedeutet, dass sie in Unterklassen nicht überschrieben werden kann. Dies ist nützlich, wenn die ursprüngliche Implementierung nicht überschrieben werden soll.
public class SuperClass{
public final void printReport(){
System.out.println("Report");
}
}
class SubClass extends SuperClass{
public void printReport(){ //Kompilierungsfehler
System.out.println("MyReport");
}
}
Für Variablen vom primitiven Typ bedeutet dies, dass der einmal zugewiesene Wert nicht mehr geändert werden kann. Für Referenzvariablen bedeutet dies, dass nach der Zuweisung eines Objekts die Referenz auf dieses Objekt nicht mehr geändert werden kann. Es ist wichtig! Der Link kann nicht geändert werden, aber der Status des Objekts kann geändert werden. Mit Java 8 erschien das Konzept - effectively final
. Es gilt nur für Variablen (einschließlich Methodenargumente). Der Punkt ist, dass sich der Wert der Variablen trotz des offensichtlichen Fehlens des Schlüsselworts final
nach der Initialisierung nicht ändert. Mit anderen Worten: Sie können eine solche Variable durch ein Wort ersetzen, final
ohne dass ein Kompilierungsfehler auftritt. effectively final
Variablen können in lokalen Klassen ( Local Inner Classes
), anonymen Klassen ( Anonymous Inner Classes
) und Streams (Stream-API) verwendet werden.
public void someMethod(){
// Im folgenden Beispiel sind sowohl a als auch b effektiv endgültig, da die Werte einmal festgelegt werden:
int a = 1;
int b;
if (a == 2) b = 3;
else b = 4;
// c ist NICHT effektiv endgültig, weil Wertänderungen
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)); //Kompilierungsfehler
}
Jetzt lasst uns ein kleines Interview führen. Schließlich besteht das Ziel des JavaRush-Kurses darin, Java-Entwickler zu werden und einen interessanten und gut bezahlten Job zu bekommen. Also, fangen wir an.
-
Was können Sie über ein Array sagen, wenn es deklariert ist
final
? -
Es ist bekannt, dass es sich um eine Klasse
String
handeltimmutable
, die Klasse deklariert wirdfinal
und der Wert der Zeichenfolge in einem Array gespeichert wirdchar
, das mit dem Schlüsselwort markiert wirdfinal
.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
Ist es möglich, den Wert eines Objekts zu ersetzen String
(ohne den Verweis auf das Objekt zu ändern)? Das sind echte Interviewfragen. Und wie die Praxis zeigt, beantworten viele sie falsch. Es ist sehr wichtig, die Verwendung des Schlüsselworts zu verstehen final
, insbesondere für Referenzvariablen. Während Sie nachdenken, ein kurzer Exkurs zum JavaRush-Team. Bitte fügen Sie in Ihrem Texteditor einen Block hinzu, der es Ihnen ermöglicht, den Inhalt auszublenden. Wenn Sie darauf klicken, wird dieser Inhalt angezeigt. Antworten:
-
Weil Ein Array ist ein Objekt, was
final
bedeutet, dass nach dem Zuweisen eines Verweises auf ein Objekt dieses nicht mehr geändert werden kann, der Zustand des Objekts jedoch geändert werden kann.final int[] array = {1,2,3,4,5}; array[0] = 9; //ok, weil Ändern Sie den Inhalt des Arrays - {9,2,3,4,5} array = new int[5]; //Kompilierungsfehler
-
Ja, du kannst. Der Schlüssel liegt darin, die Verwendung des Stachelworts
final
mit Objekten zu verstehen. Verwendet ReflectionAPI, um den Wert zu ersetzen.
import java.lang.reflect.Field;
class B {
public static void main(String[] args) throws Exception {
String value = "Old value";
System.out.println(value);
//Das Wertfeld in der String-Klasse abrufen
Field field = value.getClass().getDeclaredField("value");
//Lass es uns ändern
field.setAccessible(true);
//Neuen Wert festlegen
field.set(value, "JavaRush".toCharArray());
System.out.println(value);
/* Вывод:
* Old value
* JavaRush
*/
}
}
Bitte beachten Sie, dass nichts funktionieren würde, wenn wir versuchen würden, die letzte Variable eines primitiven Typs auf diese Weise zu ändern. Ich empfehle Ihnen, sich davon zu überzeugen: Erstellen Sie beispielsweise eine Java-Klasse mit final int
einem Feld und versuchen Sie, seinen Wert über die Reflection-API zu ändern. Allen viel Glück!
GO TO FULL VERSION