Hallo zusammen! Heute setze ich meine Überprüfung der Interviewfragen für Java-Entwickler fort.
Jetzt können wir uns die Reihenfolge der Initialisierung der Klasse (zusammen mit ihrer übergeordneten Klasse) ansehen, um besser zu verstehen, wann genau die Initialisierungsblöcke aufgerufen werden.

29. Kann return in einem Konstruktor verwendet werden?
Ja, aber nur ohne Wert rechts vom Schlüsselwort return . Sie können return verwenden ; als Hilfsanweisung in einem Konstruktor, um die Ausführung weiteren Codes dringend zu beenden (unterbrechen) und die Initialisierung des Objekts abzuschließen. Angenommen, wir haben eine Cat- Klasse und wenn eine Katze obdachlos ist ( isHomeless = true , dann möchten wir die Initialisierung beenden und die anderen Felder nicht ausfüllen (schließlich sind sie uns unbekannt, da die Katze obdachlos ist). :public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
Wenn es sich jedoch um konkrete Werte handelt, kann das Schlüsselwort „return“ keinen bestimmten Wert zurückgeben, weil:
- Wenn Sie einen Konstruktor deklarieren, haben Sie nichts Vergleichbares wie den Rückgabetyp.
- In der Regel wird der Konstruktor bei der Instanziierung implizit aufgerufen;
- Der Konstruktor ist keine Methode: Es handelt sich um einen separaten Mechanismus, dessen einziger Zweck darin besteht, Instanzvariablen zu initialisieren. Das heißt, wir verwenden den neuen Operator, um ein Objekt zu erstellen.

30. Kann ein Konstruktor eine Ausnahme auslösen?
Konstruktoren arbeiten mit Ausnahmen auf die gleiche Weise wie Methoden. Mit Methoden können wir Ausnahmen auslösen, indem wir throws <ExceptionType> in den Methodenheader schreiben. Und Konstrukteure ermöglichen es uns, dasselbe zu tun. Wenn wir den Konstruktor einer untergeordneten Klasse erben und definieren, können wir den Ausnahmetyp erweitern – zum Beispiel IOException -> Exception (aber nicht umgekehrt). Lassen Sie uns den Konstruktor der Cat- Klasse als Beispiel für einen Konstruktor verwenden, der eine Ausnahme auslöst. Nehmen wir an, dass wir beim Erstellen eines Objekts den Namen und das Alter über die Konsole eingeben möchten:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
Da Reader.readLine() eine IOException auslöst, schreiben wir diese als mögliche ausgelöste Ausnahme in den Header.
31. Was sind die Elemente eines Klassenheaders? Schreiben Sie ein Beispiel
Um die Elemente zu veranschaulichen, aus denen ein Klassenheader besteht, schauen wir uns ein kleines Schema an:- Pflichtelemente erscheinen in Klammern <>
- optionale Elemente sind in {}
public final class Lion extends Cat implements WildAnimal

32. Was sind die Elemente eines Methodenheaders? Schreiben Sie ein Beispiel
Wenn wir die Elemente betrachten, aus denen ein Methodenheader besteht, betrachten wir noch einmal ein kleines Schema:- Pflichtelemente erscheinen in Klammern <>
- optionale Elemente sind in {}
public static void main(String[] args) throws IOException
33. Erstellen Sie einen Standardkonstruktor in einer untergeordneten Klasse, wenn keiner bereits in der Basisklasse definiert ist (sondern ein anderer Konstruktor definiert ist).
Ich bin mir nicht sicher, ob ich die Frage ganz verstehe, aber vielleicht bedeutet es, dass wir in der übergeordneten Klasse einen Konstruktor wie diesen haben:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
In diesem Fall müssen wir in der übergeordneten Klasse unbedingt einen Konstruktor definieren, der die übergeordnete Klasse initialisiert (d. h. den übergeordneten Konstruktor aufruft):
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}

34. Wann wird das Schlüsselwort this verwendet?
In Java hat dies zwei verschiedene Bedeutungen. 1. Es handelt sich um eine Referenz auf das aktuelle Objekt, z. B. this.age = 9 . Das heißt, this bezieht sich auf das Objekt, in dem es verwendet wird und auf das sich der Code damit bezieht . Der Hauptzweck besteht darin, die Lesbarkeit des Codes zu verbessern und Mehrdeutigkeiten zu vermeiden. Wenn beispielsweise ein Instanzfeld und ein Methodenargument denselben Namen haben:public void setName(String name) {
this.name = name;
}
Das heißt, this.name ist das Feld des Objekts, während name der Methodenparameter ist. Die this- Referenz kann nicht in statischen Methoden verwendet werden. 2. Im Konstruktor kann dies wie eine Methode aufgerufen werden, z. B. this(value) . In diesem Fall handelt es sich um einen Aufruf eines anderen Konstruktors derselben Klasse. Grundsätzlich können Sie beim Erstellen eines Objekts zwei Konstruktoren aufrufen:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
Beim Aufruf des ersten Konstruktors zum Erstellen eines Cat- Objekts werden beide Instanzfelder erfolgreich initialisiert. Hier gibt es ein paar Nuancen:
- this() funktioniert nur in einem Konstruktor.
- Ein Verweis auf einen anderen Konstruktor muss in der ersten Zeile des Konstruktorblocks (Body) stehen. Das bedeutet, dass ein Konstruktor nicht mehr als einen (anderen) Konstruktor seiner Klasse aufrufen kann.

35. Was ist ein Initialisierer?
Soweit ich weiß, handelt es sich bei dieser Frage um gewöhnliche und statische Initialisierungsblöcke. Erinnern wir uns zunächst daran, was Initialisierung ist. Unter Initialisierung versteht man die Erstellung, Aktivierung, Vorbereitung und Definition von Feldern. Ein Programm oder eine Komponente so vorbereiten, dass sie einsatzbereit ist. Sie werden sich erinnern, dass beim Erstellen eines Objekts eine Klassenvariable sofort initialisiert werden kann, wenn sie deklariert wird:class Cat {
private int age = 9;
private String name = "Tom";
Oder nachträglich über den Konstruktor festlegen:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
Aber es gibt noch eine andere Möglichkeit: Sie können eine Instanzvariable mithilfe eines Initialisierungsblocks festlegen, der die Form von geschweiften Klammern {} innerhalb einer Klasse annimmt, ohne Namen (wie eine namenlose Methode oder ein Konstruktor):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
Ein Initialisierungsblock ist ein Codeteil, der geladen wird, wenn ein Objekt erstellt wird. Solche Blöcke werden typischerweise verwendet, um bestimmte komplexe Berechnungen durchzuführen, die beim Laden einer Klasse erforderlich sind. Die Ergebnisse dieser Berechnungen können als Werte von Variablen festgelegt werden. Neben gewöhnlichen Initialisierungsblöcken gibt es auch statische. Sie sehen gleich aus, haben aber das Schlüsselwort static vor der öffnenden geschweiften Klammer:
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
Dieser Block ist derselbe wie der vorherige. Wenn jedoch die gewöhnliche Ausführung bei der Initialisierung jedes Objekts ausgeführt wird, wird die statische Ausführung nur einmal ausgeführt, wenn die Klasse geladen wird. In der Regel werden bestimmte komplexe Berechnungen in einem statischen Block durchgeführt, der zur Initialisierung statischer Klassenvariablen verwendet wird. Für einen statischen Block gelten die gleichen Einschränkungen wie für statische Methoden: Sie können in einem statischen Block keine nicht statischen Daten verwenden, beispielsweise einen Verweis auf das aktuelle Objekt ( this ). 
36. Schreiben Sie bei einer öffentlichen Child-Klasse, die Parent erweitert, die Initialisierungsreihenfolge des Objekts auf
Beim Laden der Child- Klasse lautet die Initialisierungsreihenfolge wie folgt:- Statische Klassenfelder der übergeordneten Klasse.
- Statischer Initialisierungsblock der Parent- Klasse.
- Statische Felder der Сhild- Klasse.
- Statischer Initialisierungsblock der Child- Klasse.
- Nicht statische Felder der Parent- Klasse.
- Nicht statischer Initialisierungsblock der Parent- Klasse.
- Konstruktor der übergeordneten Klasse.
- Nichtstatische Felder der Сhild- Klasse.
- Nicht statischer Initialisierungsblock der Сhild- Klasse.
- Der Konstruktor der Сhild- Klasse.

37. Welche Beziehungen zwischen Klassen (Objekten) kennen Sie?
In Java gibt es zwei Arten von Variablen: primitive Typen und Verweise auf vollwertige Objekte.- IS-A- Beziehungen
Lion IS-A Cat
(aber nicht jede Katze ist ein Löwe ) Die gleiche Situation besteht bei Schnittstellen. Wenn die Lion- Klasse die WildAnimal- Schnittstelle implementiert , existieren sie auch in der Beziehung:
Lion IS-A WildAnimal
- HAS-A- Beziehung
Car HAS-A Passenger
Und umgekehrt: Wenn Passenger einen Verweis auf Car hat , dann ist dies die Beziehung:
Passenger HAS-A Car
38. Welche assoziativen Objektbeziehungen kennen Sie?
Aggregation und Zusammensetzung sind nichts anderes als Sonderfälle der Assoziation. Aggregation ist eine Beziehung, bei der ein Objekt Teil eines anderen ist. Beispielsweise könnte sich ein Passagier in einem Auto befinden. Darüber hinaus kann es mehrere oder gar keine Passagiere geben (und wenn wir über Tesla sprechen, gibt es möglicherweise keinen Fahrer). Zum Beispiel:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Transporting passenger - " + passenger.toString());
}
passengers.clear();
}
}
Mit anderen Worten, die Anzahl der Passagiere ist für uns nicht wichtig: Die Funktionalität der Pkw- Klasse hängt davon nicht ab. Aggregation impliziert auch, dass, wenn ein anderes Objekt ein Objekt verwendet, das erste Objekt von anderen Objekten verwendet werden kann. Beispielsweise kann derselbe Schüler sowohl in einem Strickclub als auch in einer Rockband sein und gleichzeitig einen Spanischkurs besuchen. Wie Sie sich vorstellen können, handelt es sich bei der Aggregation um eine lockerere assoziative Beziehung zwischen Klassen. Komposition ist eine noch engere Beziehung, bei der ein Objekt nicht nur Teil eines anderen Objekts ist, sondern die Arbeit eines Objekts stark von einem anderen Objekt abhängt. Ein Auto hat zum Beispiel einen Motor. Ein Motor mag ohne Auto existieren, aber außerhalb eines Autos ist er nutzlos. Und ein Auto kann nicht ohne Motor funktionieren:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
Die Zusammensetzung impliziert auch, dass, wenn ein anderes Objekt ein Objekt verwendet, das erste Objekt keinem anderen Objekt gehören darf. Um auf unser Beispiel zurückzukommen: Ein Motor kann nur zu einem Auto gehören, nicht zu zwei oder mehreren gleichzeitig. Ich denke, das reicht für heute, deshalb hören wir hier auf.
GO TO FULL VERSION