Die 50 wichtigsten Fragen und Antworten zu Java Core-Interviews. Teil 1: Die 50 wichtigsten Fragen und Antworten zu Java Core-Interviews. Teil 2
Multithreading
37. Wie erstelle ich einen neuen Thread (Flow) in Java?
Auf die eine oder andere Weise erfolgt die Erstellung durch die Verwendung der Thread-Klasse. Aber vielleicht gibt es hier Optionen...- Wir erben von
java.lang.Thread
- Wir implementieren eine Schnittstelle , deren Objekt eine Konstruktorklasse
java.lang.Runnable
akzeptiertThread
Wir erben von der Thread-Klasse
Damit dies funktioniert, erben wir in unserer Klasse vonjava.lang.Thread
. Es enthält Meth run()
, genau das, was wir brauchen. Das gesamte Leben und die gesamte Logik des neuen Threads werden in dieser Methode enthalten sein. Dies ist eine Art main
Methode für einen neuen Thread. Danach müssen Sie nur noch ein Objekt unserer Klasse erstellen und die Methode ausführen start()
, die einen neuen Thread erstellt und die darin geschriebene Logik ausführt. Lass uns nachsehen:
/**
* Пример того, Wie создавать треды путем наследования {@link Thread} класса.
*/
class ThreadInheritance extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadInheritance threadInheritance1 = new ThreadInheritance();
ThreadInheritance threadInheritance2 = new ThreadInheritance();
ThreadInheritance threadInheritance3 = new ThreadInheritance();
threadInheritance1.start();
threadInheritance2.start();
threadInheritance3.start();
}
}
Die Ausgabe an die Konsole sieht folgendermaßen aus:
Thread-1
Thread-0
Thread-2
Das heißt, auch hier sehen wir, dass die Threads nicht nacheinander ausgeführt werden, sondern wie von der JVM entschieden.)
Implementierung der Runnable-Schnittstelle
Wenn Sie gegen die Vererbung sind und/oder bereits eine der anderen Klassen erben, können Sie die verwendenjava.lang.Runnable
. Hier in unserer Klasse implementieren wir diese Schnittstelle und implementieren die Methode run()
, wie es in diesem Beispiel war. Sie müssen lediglich weitere Objekte erstellen Thread
. Es scheint, dass mehr Zeilen schlechter sind. Aber wir wissen, wie schädlich eine Vererbung ist und dass man sie unbedingt vermeiden sollte ;) Schauen wir mal:
/**
* Пример того, Wie создавать треды из интерфейса {@link Runnable}.
* Здесь проще простого - реализуем этот интерфейс и потом передаем в конструктор
* экземпляр реализуемого ein Objektа.
*/
class ThreadInheritance implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadInheritance runnable1 = new ThreadInheritance();
ThreadInheritance runnable2 = new ThreadInheritance();
ThreadInheritance runnable3 = new ThreadInheritance();
Thread threadRunnable1 = new Thread(runnable1);
Thread threadRunnable2 = new Thread(runnable2);
Thread threadRunnable3 = new Thread(runnable3);
threadRunnable1.start();
threadRunnable2.start();
threadRunnable3.start();
}
}
Und das Ausführungsergebnis:
Thread-0
Thread-1
Thread-2
38. Was ist der Unterschied zwischen einem Prozess und einem Thread?
Es gibt folgende Unterschiede zwischen einem Prozess und einem Thread:- Ein ausgeführtes Programm wird als Prozess bezeichnet, während ein Thread eine Teilmenge eines Prozesses ist.
- Prozesse sind unabhängig, während Threads eine Teilmenge eines Prozesses sind.
- Prozesse haben unterschiedliche Adressräume im Speicher, während Threads einen gemeinsamen Adressraum enthalten.
- Der Kontextwechsel ist zwischen Threads im Vergleich zu Prozessen schneller.
- Die Kommunikation zwischen Prozessen ist langsamer und teurer als die Kommunikation zwischen Threads.
- Änderungen im übergeordneten Prozess wirken sich nicht auf den untergeordneten Prozess aus, wohingegen Änderungen im übergeordneten Thread Auswirkungen auf den untergeordneten Thread haben können.
39. Was sind die Vorteile von Multithreading?
- Durch Multithreading kann eine Anwendung/ein Programm immer auf Eingaben reagieren, auch wenn bereits einige Hintergrundaufgaben ausgeführt werden.
- Mit Multithreading können Sie Aufgaben schneller erledigen, da die Threads unabhängig voneinander ausgeführt werden.
- Multithreading bietet eine bessere Cache-Auslastung, da Threads gemeinsame Speicherressourcen teilen;
- Multithreading reduziert den Serverbedarf, da ein Server mehrere Threads gleichzeitig ausführen kann.
40. Welche Zustände gibt es im Lebenszyklus eines Threads?
- Neu: In diesem Zustand wird ein Klassenobjekt
Thread
mit dem neuen Operator erstellt, der Thread existiert jedoch nicht. Der Thread startet erst, wenn wir die aufrufenstart()
. - Ausführbar: In diesem Zustand ist der Thread nach dem Aufruf der Methode zur Ausführung bereit
Start(). Es wurde jedoch noch nicht vom Thread-Scheduler ausgewählt. - Läuft: In diesem Zustand wählt der Thread-Scheduler einen Thread aus dem Bereitschaftszustand aus und führt ihn aus.
- Warten/Blockiert: In diesem Zustand wird der Thread nicht ausgeführt, ist aber noch aktiv oder wartet auf den Abschluss eines anderen Threads.
- Tot/Beendet: Wenn die Methode beendet wird,
run()
befindet sich der Thread in einem beendeten oder toten Zustand.
41. Ist es möglich, einen Thread zweimal zu starten?
Nein, wir können den Thread nicht neu starten, denn sobald der Thread gestartet und ausgeführt wird, geht er in den Dead-Zustand über. Wenn wir also versuchen, den Thread zweimal auszuführen, wird eine runtimeException „ java.lang.IllegalThreadStateException “ ausgelöst. Lass uns nachsehen:class DoubleStartThreadExample extends Thread {
/**
* Имитируем работу треда
*/
public void run() {
// что-то происходит. Для нас не существенно на этом этапе
}
/**
* Запускаем тред дважды
*/
public static void main(String[] args) {
DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
doubleStartThreadExample.start();
doubleStartThreadExample.start();
}
}
Sobald die Arbeit den zweiten Anfang desselben Threads erreicht, gibt es eine Ausnahme. Probieren Sie es selbst aus ;) Es ist besser, einmal zu sehen, als hundertmal zu hören.
42. Was passiert, wenn Sie die run()-Methode direkt aufrufen, ohne die start()-Methode aufzurufen?
Ja,run()
natürlich können Sie eine Methode aufrufen, aber dadurch wird kein neuer Thread erstellt und als separater Thread ausgeführt. In diesem Fall handelt es sich um ein einfaches Objekt, das eine einfache Methode aufruft. Wenn wir über die Methode sprechen start()
, dann ist das eine andere Sache. Indem Sie diese Methode starten, runtime
startet sie eine neue und führt wiederum unsere Methode aus ;) Wenn Sie mir nicht glauben, versuchen Sie es:
class ThreadCallRunExample extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.print(i);
}
}
public static void main(String args[]) {
ThreadCallRunExample runExample1 = new ThreadCallRunExample();
ThreadCallRunExample runExample2 = new ThreadCallRunExample();
// просто будут вызваны в потоке main два метода, один за другим.
runExample1.run();
runExample2.run();
}
}
Und die Ausgabe an die Konsole sieht folgendermaßen aus:
0123401234
Es ist ersichtlich, dass kein Thread erstellt wurde. Alles funktionierte wie in einem normalen Unterricht. Zuerst funktionierte die Methode der ersten Klasse, dann die zweite.
43. Was ist ein Daemon-Thread?
Daemon-Thread (im Folgenden als Daemon-Thread bezeichnet) ist ein Thread, der Aufgaben im Hintergrund in Bezug auf einen anderen Thread ausführt. Das heißt, seine Aufgabe besteht darin, Hilfsaufgaben auszuführen, die nur in Verbindung mit einem anderen (Haupt-)Thread erledigt werden müssen. Es gibt viele Daemon-Threads, die automatisch funktionieren, z. B. Garbage Collector, Finalizer usw.Warum schließt Java den Daemon-Thread?
Der einzige Zweck eines Daemon-Threads besteht darin, dem Benutzer-Thread Dienste für Hintergrundunterstützungsaufgaben bereitzustellen. Wenn der Hauptthread abgeschlossen ist, schließt die Laufzeit daher automatisch alle Daemon-Threads.Methoden zum Arbeiten in der Thread-Klasse
Die Klassejava.lang.Thread
stellt zwei Methoden zum Arbeiten mit dem Thread-Daemon bereit:
public void setDaemon(boolean status)
– gibt an, dass es sich um einen Daemon-Thread handelt. Der Standardwert istfalse
, was bedeutet, dass Nicht-Daemon-Threads erstellt werden, sofern nicht separat angegeben.public boolean isDaemon()
– Im Wesentlichen ist dies ein Getter für die Variabledaemon
, die wir mit der vorherigen Methode festgelegt haben.
class DaemonThreadExample extends Thread {
public void run() {
// Проверяет, демон ли этот поток oder нет
if (Thread.currentThread().isDaemon()) {
System.out.println("daemon thread");
} else {
System.out.println("user thread");
}
}
public static void main(String[] args) {
DaemonThreadExample thread1 = new DaemonThreadExample();
DaemonThreadExample thread2 = new DaemonThreadExample();
DaemonThreadExample thread3 = new DaemonThreadExample();
// теперь thread1 - поток-демон.
thread1.setDaemon(true);
System.out.println("демон?.. " + thread1.isDaemon());
System.out.println("демон?.. " + thread2.isDaemon());
System.out.println("демон?.. " + thread3.isDaemon());
thread1.start();
thread2.start();
thread3.start();
}
}
Konsolenausgabe:
демон?.. true
демон?.. false
демон?.. false
daemon thread
user thread
user thread
Aus der Ausgabe sehen wir, dass wir innerhalb des Threads selbst mithilfe einer statischen currentThread()
Methode einerseits herausfinden können, um welchen Thread es sich handelt, andererseits können wir es herausfinden, wenn wir einen Verweis auf das Objekt dieses Threads haben direkt daraus. Dies gibt die nötige Flexibilität in der Konfiguration.
44. Ist es möglich, einen Thread nach seiner Erstellung zu einem Daemon zu machen?
Nein. Wenn Sie dies tun, wird eine Ausnahme ausgelöstIllegalThreadStateException
. Daher können wir einen Daemon-Thread nur vor dem Start erstellen. Beispiel:
class SetDaemonAfterStartExample extends Thread {
public void run() {
System.out.println("Working...");
}
public static void main(String[] args) {
SetDaemonAfterStartExample afterStartExample = new SetDaemonAfterStartExample();
afterStartExample.start();
// здесь будет выброшено исключение
afterStartExample.setDaemon(true);
}
}
Konsolenausgabe:
Working...
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
at SetDaemonAfterStartExample.main(SetDaemonAfterStartExample.java:14)
45. Was ist ein Shutdownhook?
Shutdownhook ist ein Thread, der implizit aufgerufen wird, bevor die JVM (Java Virtual Machine) heruntergefahren wird. Wir können es also verwenden, um eine Ressource zu bereinigen oder den Status zu speichern, wenn die Java Virtual Machine normal oder plötzlich heruntergefahren wird. Wir könnenshutdown hook
mit der folgenden Methode hinzufügen:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Wie im Beispiel gezeigt:
/**
* Программа, которая показывает Wie запустить shutdown hook тред,
* который выполнится аккурат до окончания работы JVM
*/
class ShutdownHookThreadExample extends Thread {
public void run() {
System.out.println("shutdown hook задачу выполнил");
}
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
System.out.println("Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.");
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Konsolenausgabe:
Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.
shutdown hook задачу выполнил
46. Was ist Synchronisation?
Unter Synchronisierung versteht man in Java die Möglichkeit, den Zugriff mehrerer Threads auf eine beliebige gemeinsam genutzte Ressource zu steuern. Wenn mehrere Threads versuchen, dieselbe Aufgabe auszuführen, besteht die Möglichkeit eines fehlerhaften Ergebnisses. Um dieses Problem zu lösen, verwendet Java die Synchronisierung, wodurch jeweils nur ein Thread arbeiten kann. Die Synchronisierung kann auf drei Arten erreicht werden:- Synchronisierungsmethode
- Durch Synchronisieren eines bestimmten Blocks
- Statische Synchronisierung
Methodensynchronisation
Die synchronisierte Methode wird verwendet, um ein Objekt für eine beliebige gemeinsam genutzte Ressource zu sperren. Wenn ein Thread eine synchronisierte Methode aufruft, erwirbt er automatisch eine Sperre für dieses Objekt und gibt sie frei, wenn der Thread seine Aufgabe abgeschlossen hat. Damit es funktioniert, müssen Sie das synchronisierte Schlüsselwort hinzufügen . Sehen wir uns anhand eines Beispiels an, wie das funktioniert:/**
* Пример, где мы синхронизируем метод. То есть добавляем ему слово synchronized.
* Есть два писателя, которые хотят использовать один принтер. Они подготовoder свои поэмы
* И конечно же не хотят, чтоб их поэмы перемешались, а хотят, чтоб работа была сделана по * * * очереди для каждого из них
*/
class Printer {
synchronized void print(List<String> wordsToPrint) {
wordsToPrint.forEach(System.out::print);
System.out.println();
}
public static void main(String args[]) {
// один ein Objekt для двух тредов
Printer printer = new Printer();
// создаем два треда
Writer1 writer1 = new Writer1(printer);
Writer2 writer2 = new Writer2(printer);
// запускаем их
writer1.start();
writer2.start();
}
}
/**
* Писатель номер 1, который пишет свою поэму.
*/
class Writer1 extends Thread {
Printer printer;
Writer1(Printer printer) {
this.printer = printer;
}
public void run() {
List<string> poem = Arrays.asList("Я ", this.getName(), " Пишу", " Письмо");
printer.print(poem);
}
}
/**
* Писатель номер 2, который пишет свою поэму.
*/
class Writer2 extends Thread {
Printer printer;
Writer2(Printer printer) {
this.printer = printer;
}
public void run() {
List<String> poem = Arrays.asList("Не Я ", this.getName(), " Не пишу", " Не Письмо");
printer.print(poem);
}
}
Und die Ausgabe an die Konsole:
Я Thread-0 Пишу Письмо
Не Я Thread-1 Не пишу Не Письмо
Synchronisationsblock
Ein synchronisierter Block kann verwendet werden, um eine Synchronisierung für eine bestimmte Methodenressource durchzuführen. Nehmen wir an, dass Sie in einer großen Methode (ja, ja, so etwas kann man nicht schreiben, aber manchmal passiert es) aus irgendeinem Grund nur einen kleinen Teil synchronisieren müssen. Wenn Sie alle Codes einer Methode in einen synchronisierten Block einfügen, funktioniert dieser genauso wie eine synchronisierte Methode. Die Syntax sieht so aus:synchronized (“ein Objekt для блокировки”) {
// сам Code, который нужно защитить
}
Um das vorherige Beispiel nicht zu wiederholen, erstellen wir Threads über anonyme Klassen – das heißt, wir implementieren sofort die Runnable-Schnittstelle.
/**
* Вот Wie добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {
void print(List<String> wordsToPrint) {
synchronized (this) {
wordsToPrint.forEach(System.out::print);
}
System.out.println();
}
public static void main(String args[]) {
// один ein Objekt для двух тредов
Printer printer = new Printer();
// создаем два треда
Thread writer1 = new Thread(new Runnable() {
@Override
public void run() {
List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
printer.print(poem);
}
});
Thread writer2 = new Thread(new Runnable() {
@Override
public void run() {
List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
printer.print(poem);
}
});
// запускаем их
writer1.start();
writer2.start();
}
}
}
und Ausgabe an die Konsole
Я Writer1 Пишу Письмо
Не Я Writer2 Не пишу Не Письмо
Statische Synchronisierung
Wenn Sie eine statische Methode synchronisieren, gilt die Sperre für die Klasse und nicht für das Objekt. In diesem Beispiel wenden wir das synchronisierte Schlüsselwort auf eine statische Methode an, um eine statische Synchronisierung durchzuführen:/**
* Вот Wie добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {
static synchronized void print(List<String> wordsToPrint) {
wordsToPrint.forEach(System.out::print);
System.out.println();
}
public static void main(String args[]) {
// создаем два треда
Thread writer1 = new Thread(new Runnable() {
@Override
public void run() {
List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
Printer.print(poem);
}
});
Thread writer2 = new Thread(new Runnable() {
@Override
public void run() {
List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
Printer.print(poem);
}
});
// запускаем их
writer1.start();
writer2.start();
}
}
und die Ausgabe an die Konsole:
Не Я Writer2 Не пишу Не Письмо
Я Writer1 Пишу Письмо
47. Was ist eine volatile Variable?
Das Schlüsselwortvolatile
wird in der Multithread-Programmierung verwendet, um Thread-Sicherheit zu gewährleisten, da eine Änderung an einer veränderbaren Variablen für alle anderen Threads sichtbar ist, sodass jeweils eine Variable von jeweils einem Thread verwendet werden kann. Mit dem Schlüsselwort volatile
können Sie garantieren, dass die Variable threadsicher ist und im gemeinsam genutzten Speicher gespeichert wird und Threads sie nicht in ihren Cache aufnehmen. Wie sieht es aus?
private volatile AtomicInteger count;
Wir ergänzen einfach die Variable volatile
. Dies bedeutet jedoch nicht vollständige Thread-Sicherheit ... Schließlich sind Operationen möglicherweise nicht atomar für eine Variable. Sie können jedoch Atomic
Klassen verwenden, die die Operation atomar ausführen, also in einer einzigen Ausführung durch den Prozessor. Viele solcher Klassen sind im Paket zu finden java.util.concurrent.atomic
.
48. Was ist Deadlock?
Deadlock ist in Java Teil des Multithreadings. Ein Deadlock kann in einer Situation auftreten, in der ein Thread auf eine Objektsperre wartet, die von einem anderen Thread erworben wurde, und ein zweiter Thread auf eine Objektsperre wartet, die vom ersten Thread erworben wurde. Daher warten diese beiden Threads aufeinander und führen ihren Code nicht weiter aus. Schauen wir uns ein Beispiel an, in dem es eine Klasse gibt, die Runnable implementiert. Es akzeptiert zwei Ressourcen in seinem Konstruktor. Innerhalb der run()-Methode übernimmt sie nacheinander die Sperre für sie. Wenn Sie also zwei Objekte dieser Klasse erstellen und die Ressourcen in unterschiedlicher Reihenfolge übertragen, kann es leicht zu einer Sperre kommen:class DeadLock {
public static void main(String[] args) {
final Integer r1 = 10;
final Integer r2 = 15;
DeadlockThread threadR1R2 = new DeadlockThread(r1, r2);
DeadlockThread threadR2R1 = new DeadlockThread(r2, r1);
new Thread(threadR1R2).start();
new Thread(threadR2R1).start();
}
}
/**
* Класс, который принимает два ресурса.
*/
class DeadlockThread implements Runnable {
private final Integer r1;
private final Integer r2;
public DeadlockThread(Integer r1, Integer r2) {
this.r1 = r1;
this.r2 = r2;
}
@Override
public void run() {
synchronized (r1) {
System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (r2) {
System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r2);
}
}
}
}
Konsolenausgabe:
Первый тред захватил первый ресурс
Второй тред захватывает второй ресурс
49. Wie vermeide ich einen Deadlock?
Basierend auf dem, was wir wissen, wie ein Deadlock auftritt, können wir einige Schlussfolgerungen ziehen ...- Wie im Beispiel oben gezeigt, war der Deadlock auf die Verschachtelung von Sperren zurückzuführen. Das heißt, innerhalb einer Schleuse gibt es eine andere oder mehrere. Dies kann auf folgende Weise vermieden werden: Anstatt zu verschachteln, müssen Sie oben eine neue Abstraktion hinzufügen, die Sperre einer höheren Ebene zuweisen und verschachtelte Sperren entfernen.
- Je mehr Blockierungen vorhanden sind, desto größer ist die Wahrscheinlichkeit, dass es zu einem Deadlock kommt. Daher müssen Sie jedes Mal, wenn Sie eine Sperre hinzufügen, darüber nachdenken, ob diese wirklich benötigt wird und ob das Hinzufügen einer neuen Sperre vermieden werden kann.
- Verwendet
Thread.join()
. Ein Deadlock kann auch auftreten, wenn ein Thread auf einen anderen wartet. Um dieses Problem zu vermeiden, können Sie die Methode zeitlich begrenzenjoin()
. - Wenn wir einen Thread haben, wird es keinen Deadlock geben ;)
50. Was ist eine Rennbedingung?
Wenn in echten Rennen die Autos Leistung erbringen, dann leisten Threads in der Rennterminologie des Multithreadings Leistung in den Rennen. Aber warum? Es werden zwei Threads ausgeführt, die auf dasselbe Objekt zugreifen können. Und sie können gleichzeitig versuchen, den Zustand zu aktualisieren. Bisher ist alles klar, oder? Die Threads arbeiten also entweder real parallel (wenn mehr als ein Kern im Prozessor vorhanden ist) oder bedingt parallel, wenn der Prozessor eine kurze Zeitspanne zuweist. Und wir können diese Prozesse nicht kontrollieren, daher können wir nicht garantieren, dass ein Thread, wenn er Daten von einem Objekt liest, Zeit hat, diese zu ändern, BEVOR ein anderer Thread dies tut. Probleme wie diese treten auf, wenn diese Test-and-Act-Kombination durchgeführt wird. Was bedeutet das? Wir haben zum Beispielif
einen Ausdruck, in dessen Körper sich die Bedingung selbst ändert, nämlich:
int z = 0;
// проверь
if (z < 5) {
//действуй
z = z + 5;
}
Es kann also vorkommen, dass zwei Threads gleichzeitig in diesen Codeblock eintreten, während z noch gleich Null ist, und gemeinsam diesen Wert ändern. Und am Ende erhalten wir nicht den erwarteten Wert von 5, sondern 10. Wie kann man das vermeiden? Sie müssen vor und nach der Ausführung sperren. Das heißt, dass der erste Thread den Block betritt if
, alle Aktionen ausführt, ihn ändert z
und erst dann dem nächsten Thread die Möglichkeit gibt, dies zu tun. Aber der nächste Thread wird den Block nicht betreten if
, da z
er bereits 5 ist:
// получить блокировку для z
if (z < 5) {
z = z + 5;
}
// выпустить из блокировки z
===================================================
Statt Ausgabe
Ich möchte mich bei allen bedanken, die bis zum Ende gelesen haben. Es war eine lange Reise und du hast es geschafft! Möglicherweise ist nicht alles klar. Es ist in Ordnung. Als ich anfing, Java zu lernen, konnte ich mir nicht mehr vorstellen, was eine statische Variable ist. Aber nichts, ich schlief mit diesem Gedanken ein, las noch ein paar Quellen und verstand es schließlich. Die Vorbereitung auf ein Vorstellungsgespräch ist eher eine akademische als eine praktische Angelegenheit. Deshalb müssen Sie vor jedem Vorstellungsgespräch Dinge wiederholen und Ihr Gedächtnis auffrischen, die Sie möglicherweise nicht oft verwenden.Und wie immer nützliche Links:
- Ausnahmen in Java
- Standardmethoden in Java
- Detaillierte Analyse der ArrayList-Klasse
- Abonnieren Sie mein GitHub-Konto . Ich lege alles, was ich tue, dort hin. Alles, was ich unterrichte. Ich habe mich zum Beispiel kürzlich mit Drools RuleEngine beschäftigt .
- Aktivierte, nicht aktivierte Ausnahmen
- Versuchen Sie es mit Ressourcen
- letztes Schlüsselwort
- Während ich das Material vorbereitete, gefiel mir die Seite https://www.geeksforgeeks.org sehr gut . Da sind wirklich viele coole Informationen drin.
GO TO FULL VERSION