In den beiden vorherigen Artikeln haben wir einige wichtige Fragen besprochen, die Ihnen in Vorstellungsgesprächen am häufigsten gestellt werden. Es ist Zeit, weiterzumachen und sich die restlichen Fragen anzusehen.
Tiefes Kopieren und flaches Kopieren
Eine exakte Kopie des Originals ist sein Klon. In Java bedeutet dies, dass man ein Objekt mit einer ähnlichen Struktur wie das Originalobjekt erstellen kann. Die Methodeclone()
stellt diese Funktionalität bereit. Durch flaches Kopieren werden so wenig Informationen wie möglich kopiert. Standardmäßig ist das Klonen in Java flach, d. h. Object class
weiß nichts über die Struktur der Klasse, die es kopiert. Beim Klonen führt die JVM Folgendes aus:
- Wenn eine Klasse nur Mitglieder primitiver Typen enthält, wird eine völlig neue Kopie des Objekts erstellt und ein Verweis auf dieses Objekt zurückgegeben.
- Wenn eine Klasse nicht nur Mitglieder primitiver Typen, sondern auch Mitglieder eines beliebigen anderen Klassentyps enthält, werden Verweise auf Objekte dieser Klassen kopiert. Daher haben beide Objekte die gleichen Referenzen.
- Es besteht keine Notwendigkeit, Grunddaten separat zu kopieren.
- Alle Mitgliedsklassen in der Originalklasse müssen das Klonen unterstützen. Für jedes Klassenmitglied muss aufgerufen werden,
super.clone()
wenn die Methode überschrieben wirdclone()
. - Wenn ein Mitglied einer Klasse das Klonen nicht unterstützt, müssen Sie in der Klonmethode eine neue Instanz dieser Klasse erstellen und jedes ihrer Mitglieder mit allen Attributen einzeln in ein neues Klassenobjekt kopieren.
Was ist Synchronisation? Sperren auf Objektebene und Sperren auf Klassenebene?
Synchronisation bezieht sich auf Multithreading. Ein synchronisierter Codeblock kann jeweils nur von einem Thread ausgeführt werden. Mit Java können Sie mehrere Threads gleichzeitig verarbeiten. Dies kann dazu führen, dass zwei oder mehr Threads auf dasselbe Feld zugreifen möchten. Durch die Synchronisierung können Speicherfehler vermieden werden, die auftreten, wenn Speicherressourcen falsch genutzt werden. Wenn eine Methode als synchronisiert deklariert wird, hält der Thread seinen Monitor. Wenn zu diesem Zeitpunkt ein anderer Thread versucht, auf eine synchronisierte Methode zuzugreifen, wird der Thread blockiert und wartet darauf, dass der Monitor frei wird. Die Synchronisierung in Java wird mit dem speziellen synchronisierten Schlüsselwort erreicht . Auf diese Weise können Sie einzelne Blöcke oder Methoden in Ihrer Klasse markieren. Das synchronisierte Schlüsselwort kann nicht in Verbindung mit Klassenvariablen oder -attributen verwendet werden. Das Sperren auf Objektebene ist ein Mechanismus, wenn Sie eine nicht statische Methode oder einen nicht statischen Codeblock synchronisieren möchten, sodass nur ein Thread den Codeblock für eine bestimmte Instanz der Klasse ausführen kann. Dies sollte immer erfolgen, um die Thread-Sicherheit der Klasseninstanz zu gewährleisten. Sperren auf Klassenebene verhindern, dass mehrere Threads für alle verfügbaren Instanzen der Klasse in einen synchronisierten Block eintreten. Wenn es beispielsweise 100 Instanzen der DemoClass-Klasse gibt, kann zu einem bestimmten Zeitpunkt nur 1 Thread demoMethod() unter Verwendung einer der Variablen ausführen. Dies sollte immer erfolgen, um die Sicherheit des statischen Threads zu gewährleisten. Erfahren Sie hier mehr über die Synchronisierung.Was ist der Unterschied zwischen sleep() und wait()?
Sleep()
ist eine Methode, mit der der Vorgang um einige Sekunden verzögert wird. Im Fall von wait()
befindet sich der Thread im Wartezustand, bis wir die Methode notify()
or aufrufen notifyAll()
. Der Hauptunterschied besteht darin, dass wait()
die Monitorsperre aufgehoben wird, während sleep()
die Sperre nicht aufgehoben wird. Wait()
Wird für Multithread-Anwendungen verwendet und sleep()
dient lediglich dazu, die Thread-Ausführung anzuhalten. Thread.sleep()
Versetzt den aktuellen Thread für eine bestimmte Zeit in den Status „Nicht ausführbar“. Der Thread speichert den Status des Monitors, der vor dem Aufruf dieser Methode war. Wenn ein anderer Thread aufruft t.interrupt()
, wird der Thread, der „eingeschlafen“ ist, aktiviert. Beachten Sie, dass es sich sleep()
um eine statische Methode handelt, was bedeutet, dass sie sich immer auf den aktuellen Thread auswirkt (denjenigen, der die Methode ausführt sleep()
). t.sleep()
Ein häufiger Fehler besteht darin, „wo ist ein anderer Thread“ aufzurufen t
; selbst wenn der aktuelle Thread, der die Methode aufgerufen hat, kein Thread sleep()
ist . Versetzt den aktuellen Thread für eine Weile in den Status „Nicht ausführbar“, genau wie , jedoch mit einigen Nuancen. Wird für ein Objekt aufgerufen, nicht für einen Thread. Wir nennen dieses Objekt „Sperrobjekt“. Vor dem Aufruf muss der aktuelle Thread mit dem „Sperrobjekt“ synchronisiert werden; Danach wird diese Sperre aufgehoben und der Thread zur „Warteliste“ hinzugefügt, die dieser Sperre zugeordnet ist. Später kann sich ein anderer Thread mit demselben Sperrobjekt synchronisieren und das aufrufen . Diese Methode „weckt“ den ursprünglichen Thread auf, der noch wartet. Im Prinzip kann / mit / verglichen werden , nur dass der aktive Thread keinen direkten Zeiger auf den schlafenden Thread benötigt, sondern nur das gemeinsam genutzte Sperrobjekt kennen muss. Lesen Sie hier den detaillierten Unterschied.t
Object.wait()
sleep()
Wait()
lock.wait()
wait()
lock.notify()
wait()
notify()
sleep()
interrupt()
Ist es möglich, einer Referenzvariablen null zuzuweisen?
Nein, geht nicht. In Java muss die linke Seite des Zuweisungsoperators eine Variable sein. „This“ ist ein spezielles Schlüsselwort, das immer die aktuelle Instanz der Klasse angibt. Es ist nicht irgendeine Variable. Ebenso kann null nicht mit dem Schlüsselwort „super“ oder einem anderen ähnlichen Schlüsselwort einer Variablen zugewiesen werden.Was ist der Unterschied zwischen && und &?
&
- bitweise und &&
- logisch.
&
bewertet beide Seiten der Operation;&&
wertet die linke Seite der Operation aus. Wenn dies der Fall ist, wird weiterhin die rechte Seite ausgewertet.
Wie überschreibe ich die Methoden equal() und hachCode()?
hashCode()
und equals()
Methoden werden in der Klasse definiert Object
, die die übergeordnete Klasse für Java-Objekte ist. Aus diesem Grund erben alle Java-Objekte die Standardimplementierung für Methoden. Die Methode hashCode()
wird verwendet, um eine eindeutige Ganzzahl für ein bestimmtes Objekt zu erhalten. Diese Ganzzahl wird verwendet, um den Speicherort eines Objekts zu bestimmen, wenn dieses Objekt beispielsweise an gespeichert werden muss HashTable
. Gibt standardmäßig eine Darstellung der Adresse des Speicherorts hashCode()
zurück , an dem das Objekt gespeichert ist. Wie der Name schon sagt, dient integer
die Methode dazu, einfach zu testen, ob zwei Objekte gleich sind. equls()
Die Standardimplementierung prüft Objektreferenzen, um festzustellen, ob sie gleich sind. Nachfolgend finden Sie wichtige Richtlinien zum Neuladen dieser Methoden:
hashCode()
Verwenden Sie beim Generieren undequals()
; immer die gleichen Objektattribute .- Symmetrie. Diese.
x
Wenn es für einige Objekte „true“ zurückgibty
x.equals(y)
, sollte esy.equals(x)
„true“ zurückgeben. - Reflexivität. Denn jedes Objekt
x
x.equals(x)
muss true zurückgeben; - Konsistenz. Für alle Objekte
x
undy
x.equals(y)
gibt dasselbe zurück, wenn sich die in Vergleichen verwendeten Informationen nicht ändern; - Transitivität. Für alle Objekte
x
,y
undz
, wennx.equals(y)
es true zurückgibt undy.equals(z)
true zurückgibt, sollte esx.equals(z)
true zurückgeben; - Immer wenn während der Anwendungsausführung eine Methode für dasselbe Objekt aufgerufen wird, sollte sie dieselbe Nummer zurückgeben, es sei denn, die verwendeten Informationen ändern sich.
hashCode
kann unterschiedliche Werte für identische Objekte in verschiedenen Anwendungsinstanzen zurückgeben; - Wenn zwei Objekte laut gleich sind
equals
, müssen siehashCode
dieselben Werte zurückgeben; - Die gegenteilige Anforderung ist optional. Zwei ungleiche Objekte können denselben HashCode zurückgeben. Um die Leistung zu verbessern, ist es jedoch besser, unterschiedliche Objekte unterschiedliche Codes zurückgeben zu lassen.
Erzählen Sie uns von Zugriffsmodifikatoren
Java-Klassen, -Felder, -Konstruktoren und -Methoden können einen von vier verschiedenen Zugriffsmodifikatoren haben: private Wenn eine Methode oder Variable als privat markiert ist , kann nur Code innerhalb derselben Klasse auf die Variable zugreifen oder die Methode aufrufen. Code innerhalb von Unterklassen kann weder auf eine Variable oder Methode noch von einer anderen Klasse aus darauf zugreifen. Der private Zugriffsmodifikator wird am häufigsten für Konstruktoren, Methoden und Variablen verwendet. default Der Standardzugriffsmodifikator wird deklariert , wenn der Modifikator überhaupt nicht angegeben ist. Dieser Modifikator bedeutet, dass der Zugriff auf die Felder, Konstruktoren und Methoden einer bestimmten Klasse durch Code innerhalb der Klasse selbst und durch Code innerhalb von Klassen im selben Paket erfolgen kann. Unterklassen können nicht auf Methoden und Mitgliedsvariablen einer Oberklasse zugreifen, wenn sie als default deklariert sind , es sei denn, die Unterklasse befindet sich im selben Paket wie die Oberklasse. protected Der protected- Modifikator funktioniert genauso wie default , mit der Ausnahme, dass Unterklassen auch auf geschützte Methoden und Variablen der Oberklasse zugreifen können. Diese Aussage gilt auch dann, wenn sich die Unterklasse nicht im selben Paket wie die Oberklasse befindet. public Der Zugriffsmodifizierer public bedeutet, dass der gesamte Code auf die Klasse, ihre Variablen, Konstruktoren oder Methoden zugreifen kann, unabhängig davon, wo sich dieser Code befindet.Was ist ein Garbage Collector? Können wir ihn anrufen?
Garbage Collection ist eine Funktion der automatischen Speicherverwaltung in vielen modernen Programmiersprachen wie Java und Sprachen im NET.Framework. Sprachen, die Garbage Collection verwenden, interpretieren Garbage Collection häufig in einer virtuellen Maschine wie der JVM. Die Speicherbereinigung dient zwei Zwecken: Ungenutzter Speicher soll freigegeben werden, und Speicher darf nicht freigegeben werden, wenn das Programm ihn noch verwendet. Können Sie die Speicherbereinigung manuell ausführen? Nein,System.gc()
es gibt Ihnen so viel Zugriff wie möglich. Die beste Option besteht darin, die Methode aufzurufen System.gc()
, die dem Garbage Collector anzeigt, dass er ausgeführt werden muss. Es gibt keine Möglichkeit, es sofort auszuführen, da der Garbage Collector nicht deterministisch ist. Darüber hinaus erfolgt laut Dokumentation OutOfMemoryError
keine Weiterleitung, wenn die virtuelle Maschine nach einer vollständigen Garbage Collection keinen Speicher freigeben konnte. Erfahren Sie hier mehr über Garbage Collector.
Was bedeutet das native Schlüsselwort? Erkläre im Detail
Das native Schlüsselwort wird verwendet, um anzugeben, dass die Methode in einer anderen Programmiersprache als einer Java-Datei implementiert ist. In der Vergangenheit wurden native Methoden verwendet. In aktuellen Java-Versionen wird dies seltener benötigt. Derzeit werden native Methoden benötigt, wenn:- Sie müssen eine Bibliothek aus Java aufrufen, die in einer anderen Sprache geschrieben ist.
- Sie benötigen Zugriff auf System- oder Hardwareressourcen, auf die nur mit einer anderen Sprache (normalerweise C) zugegriffen werden kann. Tatsächlich können viele Systemfunktionen, die mit dem realen Computer interagieren (z. B. Festplatten oder Netzwerkdaten), nur mit der nativen Methode aufgerufen werden.
- JNI/JNA kann die JVM destabilisieren, insbesondere wenn Sie versuchen, etwas Komplexes zu tun. Wenn Ihre native Methode etwas falsch macht, besteht die Möglichkeit, dass die JVM abstürzt. Außerdem können schlimme Dinge passieren, wenn Ihre native Methode von mehreren Threads aufgerufen wird. Usw.
- Es ist schwieriger, ein Programm mit nativem Code zu debuggen.
- Nativer Code erfordert eine separate Erstellung von Frameworks, was zu Problemen bei der Portierung auf andere Plattformen führen kann.
Was ist Serialisierung?
In der Informatik ist Serialisierung im Kontext der Datenspeicherung und -übertragung der Prozess der Übersetzung einer Datenstruktur oder des Zustands eines Objekts in ein Format, das gespeichert und später in einer anderen Computerumgebung abgerufen werden kann. Nach dem Empfang einer Reihe von Bits werden diese gemäß dem Serialisierungsformat neu berechnet und können zur Erstellung eines semantisch identischen Klons des Originalobjekts verwendet werden. Java bietet eine automatische Serialisierung, die erfordert, dass das Objekt die Schnittstelle implementiertjava.io.Serializable
. Die Schnittstellenimplementierung markiert die Klasse als „serialisierbar“. Die java.io.Serializable-Schnittstelle verfügt über keine Serialisierungsmethoden, aber die serialisierbare Klasse kann optional Methoden definieren, die als Teil des Serialisierungs-/Diserialisierungsprozesses aufgerufen werden. Wenn Sie Änderungen an Klassen vornehmen, müssen Sie berücksichtigen, welche mit der Serialisierung kompatibel sind und welche nicht. Die vollständige Anleitung können Sie hier lesen. Ich werde die wichtigsten Punkte nennen: Inkompatible Änderungen:
- Ein Feld löschen;
- Eine Klasse in der Hierarchie nach oben oder unten verschieben;
- Ändern eines nichtstatischen Feldes in ein statisches oder eines nichttransienten in ein transientes Feld;
- Ändern des deklarierten primitiven Datentyps;
- Ändern Sie die Methode
WriteObject
entwederReadObject
so, dass Felder standardmäßig nicht mehr geschrieben oder gelesen werden. - Klassenwechsel oder
Serializable
umgekehrtExternalizable
; - Ändern einer Enum- Klasse in eine Nicht-Enum-Klasse oder umgekehrt;
- Entfernen
Serializable
oderExternalizable
; - Hinzufügen
writeReplace
einerreadResolve
Methode zu einer Klasse.
- Felder hinzufügen;
- Klassen hinzufügen/entfernen;
- Methoden hinzufügen
WriteObject/ReadObject
[MethodendefaultReadObject
oderdefaultWriteObject
müssen am Anfang aufgerufen werden]; - Methoden entfernen
WriteObject/ReadObject
; - Zusatz
java.io.Serializable
; - Feldzugang ändern;
- Ein statisches Feld in ein nichtstatisches oder ein transientes in ein nichttransientes Feld ändern .
GO TO FULL VERSION