
Fragen und Antworten für eine Junior-Entwicklerposition
Allgemeine Fragen
1. Welche Designmuster kennen Sie? Erzählen Sie uns von zwei Designmustern, die Sie in Ihrer Arbeit verwendet haben.
Es gibt eine große Vielfalt an Mustern. Wer sich gründlich mit Design Patterns vertraut machen möchte, dem empfehle ich die Lektüre des Buches „Head First. Design Patterns“. Es wird Ihnen helfen, die Details der grundlegendsten Entwurfsmuster leicht zu erlernen. Wenn es um Designmuster geht, die Sie in einem Vorstellungsgespräch erwähnen könnten, fallen Ihnen folgende ein:- Builder – eine häufig verwendete Vorlage, eine Alternative zum klassischen Ansatz zur Objekterstellung;
- Strategie – ein Muster, das im Wesentlichen Polymorphismus darstellt. Das heißt, wir haben eine Schnittstelle, aber das Verhalten des Programms ändert sich abhängig von der spezifischen Schnittstellenimplementierung, die an die Funktion übergeben wird (das Strategiemuster wird mittlerweile fast überall in Java-Anwendungen verwendet).
- Factory – dieses Muster kann in ApplicationContext (oder in BeanFactory) gefunden werden;
- Singleton – alle Beans sind standardmäßig Singletons;
- Proxy – im Grunde verwendet alles in Spring dieses Muster auf die eine oder andere Weise, zum Beispiel AOP;
- Verantwortungskette – ein Muster, das Spring Security zugrunde liegt;
- Vorlage – wird in Spring JDBC verwendet.
Java Core

2. Welche Datentypen gibt es in Java?
Java verfügt über die folgenden primitiven Datentypen:- Byte – Ganzzahlen im Bereich von -128 bis 127, nehmen 1 Byte ein;
- short – Ganzzahlen im Bereich von -32768 bis 32767, belegen 2 Bytes;
- int – Ganzzahlen im Bereich von -2147483648 bis 2147483647, belegen 4 Bytes;
- long – Ganzzahlen im Bereich von 9223372036854775808 bis 9223372036854775807, belegen 8 Bytes;
- float – Gleitkommazahlen im Bereich von -3,4E+38 bis 3,4E+38, belegen 4 Bytes;
- double – Gleitkommazahlen im Bereich von -1,7E+308 bis 1,7E+308, belegen 8 Bytes;
- char – einzelne Zeichen in UTF-16, belegt 2 Bytes;
- boolesche Wahr/Falsch-Werte, nehmen 1 Byte ein.
3. Wie unterscheidet sich ein Objekt von primitiven Datentypen?
Der erste Unterschied besteht in der Menge des belegten Speichers: Grundelemente beanspruchen sehr wenig, da sie nur ihren eigenen Wert enthalten, Objekte können jedoch viele verschiedene Werte enthalten – sowohl Grundelemente als auch Verweise auf andere Objekte. Ein zweiter Unterschied besteht darin: Java ist eine objektorientierte Sprache, daher ist alles, was in Java funktioniert, eine Interaktion zwischen Objekten. Primitive passen hier nicht so gut hinein. Aus diesem Grund ist Java keine zu 100 % objektorientierte Sprache. Der dritte Unterschied, der sich aus dem zweiten ergibt, besteht darin, dass es viele verschiedene Mechanismen zum Verwalten von Objekten gibt, da Java auf Objektinteraktionen ausgerichtet ist. Zum Beispiel Konstruktoren, Methoden, Ausnahmen (die hauptsächlich mit Objekten funktionieren) usw. Und damit Grundelemente irgendwie in dieser objektorientierten Umgebung funktionieren können, haben sich die Entwickler von Java etwas ausgedachtWrapper für die primitiven Typen ( Integer , Character , Double , Boolean ...)4. Was ist der Unterschied zwischen der Übergabe von Argumenten nach Referenz und nach Wert?
Primitive Felder speichern ihren Wert: Wenn wir beispielsweise int i = 9; , dann speichert das i- Feld den Wert 9. Wenn wir einen Verweis auf ein Objekt haben, bedeutet das, dass wir ein Feld mit einem Verweis auf das Objekt haben. Mit anderen Worten, wir haben ein Feld, das die Adresse des Objekts im Speicher speichert.
Cat cat = new Cat();
Das bedeutet, dass Felder mit Bezug auf ein Objekt auch Werte speichern . Ihre Werte sind Speicheradressen. Das heißt, cat speichert die Speicheradresse des neuen Cat()- Objekts. Wenn wir ein Argument an eine Methode übergeben, wird sein Wert kopiert. Im Falle eines Primitivs wird der Wert des Primitivs kopiert. Dementsprechend funktioniert die Methode mit der Kopie. Bei einer Änderung der Kopie ist das Original nicht betroffen. Bei einem Referenztyp wird der Wert der Speicheradresse kopiert. Dementsprechend speichern beide Referenzvariablen Adressen, die auf dasselbe Objekt verweisen. Und wenn wir diese neue Referenz verwenden, um das Objekt zu ändern, werden wir feststellen, dass es auch für die alte Referenz geändert wird. Schließlich zeigen beide auf dasselbe Objekt.
5. Was ist JVM, JDK und JRE?
JVM steht für Java Virtual Machine , auf der der vom Compiler vorgenerierte Java-Bytecode ausgeführt wird. JRE steht für Java Runtime Environment . Im Grunde handelt es sich um eine Umgebung zum Ausführen von Java-Anwendungen. Es umfasst die JVM, Standardbibliotheken und andere Komponenten zum Ausführen von Applets und Anwendungen, die in der Programmiersprache Java geschrieben sind. Mit anderen Worten: Die JRE ist ein Paket mit allem, was zum Ausführen eines kompilierten Java-Programms erforderlich ist, enthält jedoch keine Tools und Dienstprogramme wie Compiler oder Debugger zum Entwickeln von Anwendungen. JDK steht für Java Development Kit und ist eine Erweiterung des JRE. Das heißt, es handelt sich um eine Umgebung, in der Java-Anwendungen nicht nur ausgeführt, sondern auch entwickelt werden können. Das JDK enthält alles in der JRE sowie verschiedene zusätzliche Tools – Compiler und Debugger –, die zum Erstellen von Java-Anwendungen erforderlich sind (einschließlich Java-Dokumente).
6. Warum die JVM verwenden?
Wie oben erwähnt, ist die Java Virtual Machine eine virtuelle Maschine, die Java-Bytecode ausführt, der vom Compiler vorgeneriert wurde. Dies bedeutet, dass die JVM den Java-Quellcode nicht versteht. Also kompilieren wir zunächst .java- Dateien. Die kompilierten Dateien haben die .classErweiterung und liegen nun in Form von Bytecode vor, den die JVM versteht. Die JVM ist für jedes Betriebssystem unterschiedlich. Wenn die JVM Bytecode-Dateien ausführt, passt sie diese an das Betriebssystem an, auf dem sie ausgeführt wird. Da es verschiedene JVMs gibt, unterscheidet sich tatsächlich auch das JDK (oder JRE) für verschiedene Betriebssysteme (jede Version benötigt ihre eigene JVM). Erinnern wir uns daran, wie die Entwicklung in anderen Programmiersprachen funktioniert. Sie schreiben ein Programm, dann wird sein Code in Maschinencode für ein bestimmtes Betriebssystem kompiliert und Sie können es dann ausführen. Mit anderen Worten: Sie müssen für jede Plattform unterschiedliche Versionen des Programms schreiben. Aber durch die doppelte Verarbeitung des Codes durch Java (Kompilierung des Quellcodes in Bytecode und anschließende Verarbeitung des Bytecodes durch die JVM) können Sie die Vorteile einer plattformübergreifenden Lösung genießen. Wir erstellen den Code einmal und kompilieren ihn in Bytecode. Dann können wir es auf jedes Betriebssystem übertragen und die native JVM kann es ausführen. Und genau das ist Javas LegendeFunktion „Einmal schreiben, überall ausführen“ .
7. Was ist Bytecode?
Wie ich oben sagte, konvertiert der Compiler Java-Code in Zwischenbytecode ( wir gehen von Dateien mit der Erweiterung .java zu Dateien mit der Erweiterung .class über). In vielerlei Hinsicht ähnelt Bytecode dem Maschinencode, mit der Ausnahme, dass sein Befehlssatz nicht für einen realen, sondern einen virtuellen Prozessor gilt. Allerdings kann es Abschnitte enthalten, die für einen JIT-Compiler entwickelt wurden, der die Befehlsausführung für den tatsächlichen Prozessor optimiert, auf dem das Programm ausgeführt wird. Die JIT-Kompilierung, auch On-the-Fly-Kompilierung genannt, ist eine Technologie, die die Leistung eines Bytecode-Programms steigert, indem sie den Bytecode während der Ausführung des Programms in Maschinencode oder ein anderes Format kompiliert. Wie Sie vielleicht schon vermutet haben, verwendet die JVM den JIT-Compiler, wenn sie Bytecode ausführt. Schauen wir uns einen Beispiel-Bytecode an:
8. Was sind die Funktionen einer JavaBean?
Ein JavaBean ist eine Java-Klasse, die bestimmten Regeln folgt. Hier sind einige Regeln zum Schreiben einer JavaBean :-
Die Klasse muss einen leeren Konstruktor (ohne Argumente) mit dem öffentlichen Zugriffsmodifikator enthalten. Dieser Konstruktor ermöglicht es, ohne unnötige Probleme ein Objekt der Klasse zu erstellen (so dass kein unnötiges Hantieren mit Argumenten entsteht).
-
Der Zugriff auf interne Felder erfolgt über die Instanzmethoden get und set , die über die Standardimplementierung verfügen sollten. Wenn wir beispielsweise ein Namensfeld haben , sollten wir getName und setName usw. haben. Dadurch können verschiedene Tools (Frameworks) den Inhalt von Beans ohne Schwierigkeiten automatisch abrufen und festlegen.
-
Die Klasse muss die Methoden equal() , hashCode() und toString() überschreiben .
-
Die Klasse muss serialisierbar sein. Das heißt, es muss über die Serializable-Markerschnittstelle verfügen oder die Externalizable- Schnittstelle implementieren. Auf diese Weise kann der Zustand der Bean zuverlässig gespeichert, gespeichert und wiederhergestellt werden.

9. Was ist ein OutOfMemoryError?
OutOfMemoryError ist ein kritischer Laufzeitfehler im Zusammenhang mit der Java Virtual Machine (JVM). Dieser Fehler tritt auf, wenn die JVM ein Objekt nicht zuweisen kann, weil nicht genügend Speicher dafür vorhanden ist und der Garbage Collector keinen weiteren Speicher zuweisen kann. Einige Arten von OutOfMemoryError :-
OutOfMemoryError: Java-Heap-Speicherplatz – Das Objekt kann aufgrund unzureichenden Speichers nicht auf dem Java-Heap zugewiesen werden. Dieser Fehler kann durch einen Speicherverlust oder durch eine Standard-Heap-Größe verursacht werden, die für die aktuelle Anwendung zu klein ist.
-
OutOfMemoryError: GC-Overhead-Grenze überschritten – da die Daten der Anwendung kaum in den Heap passen, läuft der Garbage Collector ständig, was dazu führt, dass das Java-Programm sehr langsam läuft. Dadurch wird der Overhead-Grenzwert des Garbage Collectors überschritten und die Anwendung stürzt mit diesem Fehler ab.
-
OutOfMemoryError: Die angeforderte Array-Größe überschreitet die VM-Grenze – dies weist darauf hin, dass die Anwendung versucht hat, Speicher für ein Array zu reservieren, das die Heap-Größe überschreitet. Auch dies kann bedeuten, dass standardmäßig nicht genügend Speicher zugewiesen wurde.
-
OutOfMemoryError: Metaspace – Dem Heap ist nicht mehr genügend Speicherplatz für Metadaten zugewiesen (Metadaten sind Anweisungen für Klassen und Methoden).
-
OutOfMemoryError: Größe Bytes aus Gründen anfordern. Nicht genügend Auslagerungsspeicher – beim Versuch, Speicher vom Heap zuzuordnen, ist ein Fehler aufgetreten, weshalb auf dem Heap nicht genügend Speicherplatz vorhanden ist.
10. Was ist ein Stacktrace? Wie bekomme ich es?
Ein Stacktrace ist eine Liste der Klassen und Methoden, die bis zu diesem Punkt bei der Ausführung einer Anwendung aufgerufen wurden. Sie können den Stack-Trace an einem bestimmten Punkt in der Anwendung abrufen, indem Sie folgendermaßen vorgehen:
StackTraceElement[] stackTraceElements =Thread.currentThread().getStackTrace();
Dadurch erhalten wir ein Array von StackTraceElements, die in der LIFO-Reihenfolge (Last In First Out) angeordnet sind . 
StackTraceElement[] stackTraceElements;
try{
...
} catch (Exception e) {
stackTraceElements = e.getStackTrace();
}
Und wenn wir den Stack-Trace einer Ausnahme auf der Konsole anzeigen möchten:
try{
...
} catch (Exception e) {
e.printStackTrace();
}
Wenn außerdem ein Fehler, eine ungeprüfte Ausnahme oder eine nicht behandelte geprüfte Ausnahme auftritt, erhalten wir automatisch den Stack-Trace der Ausnahme auf der Konsole, wenn die Anwendung abstürzt. Hier ist ein kleines Beispiel für einen Stacktrace auf der Konsole: 

GO TO FULL VERSION