Das Folgende wird für jedes Missverständnis für alle angezeigt.
1. Nulls übermäßiger Gebrauch
Das Vermeiden von übermäßigem Gebrauch von NULL ist die beste Praxis. Ein besserer Ansatz besteht beispielsweise darin, die Methode anstelle des Nullwerts zum leeren Array oder zur Sammlung zurückzukehren, da dies verhindern kann, dass das Programm NullPoInterexception abwirft. Das folgende Codefragment erhält eine Sammlung von einer anderen Methode:
Liste <String> KontoIDs = person.getAccountids ();
Wenn eine Zahl kein Konto hat, gibt GetAccountids () den Nullwert zurück, und das Programm wird die Ausnahme von NullPointerexception auswerfen. Daher ist es notwendig, sich der Luftprüfung beizutragen, um dieses Problem zu lösen. Wenn Sie den zurückgegebenen Nullwert durch eine leere Liste ersetzen, wird NullPoInterException nicht angezeigt. Da wir nicht mehr eine kurze Überprüfung der variablen Kontoe durchführen müssen, wird der Code prägnanter.
Wenn Sie Nullwerte vermeiden möchten, können unterschiedliche Szenarien unterschiedliche Praktiken annehmen. Eine Methode besteht darin, den optionalen Typ zu verwenden, der sowohl ein leeres Objekt als auch ein Paket einiger Werte sein kann.
Optional <string> optionalString = optional.ofnullable (nulledString);
Tatsächlich bietet Java8 einen prägnanteren Weg:
Optional <string> optionalString = optional.ofnulable (nullialstring);
Java hat den optionalen Typ aus der Java8 -Version unterstützt, war jedoch in der funktionalen Programmierwelt weithin bekannt. Zuvor wurde es in der frühen Version von Java in Google Guava verwendet.
2. Ignorieren Sie Abnormalitäten
Wir ignorieren oft Anomalien. Die beste Praxis ist jedoch, mit ihnen für Anfänger und erfahrene Java -Programmierer umzugehen. Das abnormale Wurf ist normalerweise zielgerichtet. In den meisten Fällen ist es erforderlich, Ereignisse aufzuzeichnen, die Anomalien verursachen. Unterschätzen Sie diese Angelegenheit nicht. Um andere Entwickler über die Ursache und die Wirkung zu informieren, sollten Sie zumindest erklären, warum diese Anomalien nicht behandelt wurden.
Selfie = person.shootaselfie ();
Eine einfache Möglichkeit, einen bestimmten unwichtigen Wert zu betonen, besteht darin, diese Informationen als abnormaler variabler Name wie folgt zu verwenden:
Kopieren Sie den Code -Code wie folgt:
try {selfie.delete ();} catch (nullpointterException unwichtig) {}
3.. Ändern Sie die Anomalien gleichzeitig
Diese Abnormalität tritt im Sammelobjekt auf und verwendet gleichzeitig nicht die vom Iteratorobjekt bereitgestellte Methode, um den Inhalt in der Sammlung zu aktualisieren. Zum Beispiel gibt es hier eine Hatsliste, und Sie möchten alle Werte löschen, die Ohrklappen enthalten:
Liste <iHats = New ArrayList <> (); hasearFlaps ()) {Hats.remove (Hat);}}
Wenn dieser Code ausgeführt wird, wird die ConcurrentModificationException ausgeworfen, da der Code ihn beim Durchqueren dieser Sammlung ändert. Wenn mehrere Prozesse auf derselben Liste wirken, versucht der andere Prozess, den Listeninhalt zu ändern, und dieselben Anomalien können ebenfalls auftreten, wenn einer der Prozesse die Liste durchquert.
Es ist in Multi -Thread -gleichzeitigen Veränderungs -Sammlungsinhalten sehr häufig, daher ist es erforderlich, die Methode zu verwenden, die üblicherweise bei der gleichzeitigen Programmierung verwendet wird, z. B. synchrone Schlösser, spezielle Sets für die gleichzeitige Modifikation usw. Java löst dieses Problem in einem einzigen Thread und einer Situation mit mehreren Threads.
Sammeln Sie Objekte und löschen Sie sie in einem anderen Zyklus
Die direkte Lösung besteht darin, Hüte mit Ohrklappen in eine Liste zu stecken und sie dann mit einem anderen Zyklus zu löschen. Dies erfordert jedoch einen zusätzlichen Satz, um zu löschende Hüte zu speichern.
Liste <Ihatstoremove = new LinkedList <> ();
Verwenden Sie die Methode iterator.remove
Diese Methode ist einfacher und muss gleichzeitig keine zusätzliche Sammlung erstellen:
Iterator <Ihatitrator = Hats.iterator ();
Die Methode der Verwendung von Listiterator
Wenn die Sammlung der Sammlung der Listenschnittstelle implementiert wird, ist der List -Iterator eine sehr geeignete Wahl. Iterator, der die Listitoror -Schnittstelle implementiert, unterstützt nicht nur Löschvorgänge, sondern auch das Hinzufügen und Setzen von Vorgängen. Die Listotriator -Schnittstelle implementiert die Iteratorschnittstelle, sodass dieses Beispiel der Iteratormethode entfernen. Der einzige Unterschied ist der Hut -Iterator, und wir erhalten die Iteratormethode -mit der Methode ListotRator (). Die folgenden Fragmente zeigen, wie Sie die Methode "Listterator.Remove und ListotRator.ADD" verwenden, um den Ohrklappenhut durch Som <ombreros zu ersetzen.
IHat sombrero = neuer sombrero (); ;
Wenn Sie ListIterator verwenden, können Sie die Methode entfernen und hinzufügen, um nur eine eingestellte Methode aufzurufen:
Ihat sombrero = new sombrero (); ); // einstellen und addieren}}}
Verwenden Sie die Stream -Methode in Java 8
In Java8 können Entwickler eine Sammlung in Stream- und Filterstrom gemäß einigen Bedingungen umwandeln. In diesem Beispiel wird angegeben, wie die Stream -API -Filterhüte und die ConcurrentModificationException vermeiden. hats = Hats.stream ().
Kopieren Sie den Code -Code wie folgt:
.Collect (Collectors.Tocollection (ArrayList :: New));
Die Methode für Sammler. Wenn die Filterbedingungen eine große Anzahl von Einträgen herausgefiltert werden, wird hier eine große Arraylist generiert. Daher müssen Sie es mit Vorsicht verwenden.
Verwenden Sie die Liste der Liste.Removeif in Java 8
Sie können eine andere prägnantere und klare Methode in der Java 8 -Removef -Methode verwenden:
Kopieren Sie den Code -Code wie folgt:
Hats.removeif (ihat :: Hasearflaps);
Unten verwendet es Iterator.Remove, um diesen Vorgang abzuschließen.
Verwenden Sie eine spezielle Sammlung
Wenn Sie sich für die Verwendung von CopyonWriteArrayList anstelle von ArrayList am Anfang entscheiden, wird es kein Problem geben. Da CopyonWriteArrayList modifizierte Methoden (z. B. festgelegt, hinzufügen, entfernen) enthält, wird das ursprüngliche Sammlungsarray nicht geändert, sondern eine neue geänderte Version erstellt. Dies ermöglicht es, die Originalversion zu ändern, sodass die ConcurrentModificationException nicht ausgeworfen wird. Die Nachteile dieser Sammlung sind auch sehr offensichtlich -eine neue Sammlung wird für jede Modifikation generiert.
Es gibt andere Sätze, die für verschiedene Szenarien geeignet sind, wie Copyonwriteset und Concurrenthashmap.
In Bezug auf einen weiteren Fehler, der bei gleichzeitigen Modifikationen auftreten kann, erzeugt es einen Stream aus einer Sammlung. Das allgemeine Kriterium für den Stream besteht darin, bei der Überprüfung des Streams die Änderung der Rückseite der Back -End -Sammlung zu vermeiden. Das nächste Beispiel zeigt, wie man den Stream richtig behandelt:
Liste <Ihat> filedHats = hass.stream ().
Die Peek -Methode sammelt alle Elemente und führt etablierte Aktionen für jedes Element aus. Hier besteht die Aktion darin, Daten aus einer grundlegenden Liste zu löschen, was offensichtlich falsch ist. Um solche Operationen zu vermeiden, können Sie einige oben erläuterte Methoden ausprobieren.
4. Verteidigung
Manchmal muss der von der Standardbibliothek oder Dritte bereitgestellte Code, um besser zusammenzuarbeiten, gemeinsame Abhängigkeiten einhalten. Beispielsweise ist es erforderlich, die gemeinsame Übereinstimmung zwischen HashCode und Equals einzuhalten, um sicherzustellen, dass eine Reihe von Sammelklassen im Java -Sammelframework und andere Klassen unter Verwendung des HashCode- und Equals -Methoden normal funktionieren können. Machen Sie keine Fehler wie Ausnahme oder Zerstörung der Codekompilierung.
Der Fehlercode kann sich in die Produktionsumgebung einschalten und viele nachteilige Auswirkungen haben. Dies umfasst schlechte UI -Erfahrung, falsche Datenberichte, schlechte Anwendungsleistung, Datenverlust oder mehr. Glücklicherweise treten diese katastrophalen Fehler nicht oft auf. Der HashCode und die Gleichen wurden bereits erwähnt, dass die Szene, die sie erscheint, sein kann: Die Sammlung hängt vom Ziel ab, die Objekte oder Vergleiche zu vergleichen, genau wie Hashmap und Hashset. In einfachen Worten gibt es zwei Kriterien für diese Vereinbarung:
Wenn die beiden Objekte gleich sind, muss der Hash -Code gleich sein.
Wenn die beiden Objekte den gleichen Hash -Code haben, können sie gleich oder unterschiedlich sein.
Das erste Kriterium für die Zerstörung, wenn Sie versuchen, Daten aus einem HashMap abzurufen, wird dies zu Fehlern führen. Das zweite Kriterium bedeutet, dass Objekte mit demselben Hash -Code nicht unbedingt gleich sind.
Schauen wir uns die Folgen der Zerstörung des ersten Kriteriums an:
Öffentliches statisches Klassenboot {private String -Name; GetClass ()! int HashCode () {return (int) (math.random () * 5000);}}
Wie Sie sehen können, schreiben die Bootsklasse die Methoden für Gleichen und Hashcode neu. Es hat jedoch die Vereinbarung zerstört, da HashCode den Zufallswert für dasselbe Objekt für jeden Anruf zurückgegeben hat. Der folgende Code findet wahrscheinlich kein Boot namens Enterprise in Hashset, obwohl wir diese Art von Boot tatsächlich im Voraus hinzugefügt haben:
Public static void main (String [] args) {set <boot> boots = new Hashset <> (); (Neues Boot ("Enterprise");};};
Eine weitere Vereinbarung ist die Abschlussmethode. Hier ist ein Verweis auf das offizielle Java -Dokument zu seiner funktionalen Beschreibung:
Die konventionelle Übereinstimmung von Finalize lautet: Wenn die virtuelle Javatm -Maschine feststellt, dass ein Thread in keiner Weise auf das angegebene Objekt zugreifen kann, wird diese Methode aufgrund eines bestimmten Verhaltens aufgerufen. Die Abschlussmethode verfügt über mehrere Funktionen, einschließlich der Verwendung dieses Objekts, um anderen Threads erneut zur Verfügung zu stehen. Beispielsweise kann die Abschlussmethode, die das Eingabe-/Ausgangsverbindungsobjekt angibt, die explizite E/A -Transaktion ausführen, um die Verbindung vor dem dauerhaften weggeworfenen Objekt zu unterbrechen.
Sie können beschließen, die Abschlussmethode in einem Dateiprozessor zu verwenden, um Ressourcen zu veröffentlichen, aber diese Verwendung ist schlecht. Da es während des Müllrecyclings aufgerufen wird und die Zeit von GC nicht sicher ist, wird die Zeit für die Finalisierung nicht garantiert.
5. Verwenden Sie den ursprünglichen Typ anstelle der Parametrisierung
Gemäß der Java -Dokumentbeschreibung: Der ursprüngliche Typ ist entweder nicht parametrisiert oder ein nicht -statisches Mitglied des nicht -statischen Mitglieds von R (auch Nicht -Inhoritanz von R -übergeordneter oder übergeordneter Schnittstelle). Bevor der java generische Typ eingeführt wurde, gab es keinen primitiven alternativen Typ. Java hat die generische Programmierung von Version 1.5 unterstützt, und es besteht kein Zweifel, dass dies eine wichtige Funktionsverbesserung ist. Aufgrund der Rückwärtskompatibilität gibt es hier jedoch eine Falle, die das gesamte Typsystem zerstören kann. Streben Sie das Beispiel an:
Listofnumbers = new ArrayList ();
Dies ist eine Liste von Zahlen, die als ursprüngliche ArrayList definiert sind. Da es die Typparameter nicht angeben, kann es ein Objekt hinzufügen. Die letzte Zeile ordnet jedoch die Elemente ab, die sie enthält, und multipliziert mit 2, druckte die Daten nach doppelt so doppelter Daten in die Standardausgabe aus.
Dieser Code macht während der Kompilierung keinen Fehler, aber sobald er ausgeführt wird, macht er beim Laufen einen Fehler, da er versucht, den Zeichentyp auf plastische Chirurgie zuzuordnen. Wenn die erforderlichen Informationen versteckt sind, hilft das Typsystem nicht, einen Sicherheitscode zu schreiben.
Um dieses Problem zu lösen, müssen Sie den spezifischen Typ für die Objekte in der Sammlung angeben:
LISTE <NEGEGER> LISTOFNUMBERS = Neue Arraylist <() ();
Der einzige Unterschied zum vorherigen Code ist die Zeile, die die Sammlung definiert:
Kopieren Sie den Code -Code wie folgt:
Liste <Ganzzahl> listofnumbers = new ArrayList <();
Die geänderte Code -Kompilierung kann nicht übergeben werden, da versucht wird, der Sammlung von nur erwarteten Speicherplastik eine Zeichenfolge hinzuzufügen. Der Compiler zeigt eine Fehlermeldung an und verweist auf die Zeile, die der Liste zwanzig Zeichen hinzufügt. Parametrisierung generischer Typ ist eine gute Idee. In diesem Fall kann der Compiler die möglichen Typen überprüfen, damit die abnormale Laufzeitwahrscheinlichkeit aufgrund von Inkonsistenzen stark reduziert wird.
Die Hauptübersicht der oben genannten fünf Java -Programmierer macht oft Fehler, ich hoffe, es kann es mögen.