Redewendungen der Java-Sprache
1. Zyklus
Eliminieren Sie in wichtigen Schleifen Methodenaufrufe, wenn Sie den Schleifenabschluss bestimmen.
Zum Beispiel: Wille
for(int i=0; i<collection.size();i++){ ... }
Ersetzen durch…
for(int i=0; n=collection.size();i<n;i++){...}
Normalerweise werden Elemente, die nicht mit dem Schleifenindex in Zusammenhang stehen, außerhalb der Schleife verschoben.
for(int i=0; terminal=x.length;i<terminal;i++){x[i] = x[i]/scaleA *scaleB;}
Es sollte sein:
Doppelte Skala = scaleB*scaleA;for(int i=0; terminal=x.length;i<terminal;i++){x[i] = x[i]/scale;}
2. Zeichenfolge
Beseitigen Sie die Verkettung von Zeichenfolgen
Verwenden Sie beim Erstellen langer Zeichenfolgen immer StringBuffter anstelle von String
StringBuffer-Speicherplatz vorab zuweisen StringBuffer sb = new StringBuffer(5000);
3. Grundlegende Datentypen
Verwenden Sie grundlegende Datentypen in wichtigen Schleifen (int-Daten sind normalerweise schneller als long/double-Daten)
Wrapping-Klassen grundlegender Datentypen (Boolescher Wert, Ganzzahl usw.) werden hauptsächlich verwendet, wenn der übergebene Methodenparameter eine Referenz auf ein Objekt sein muss (und nicht auf einen grundlegenden Datentyp).
Verwenden Sie den statischen Endmodifikator für alle konstanten algebraischen Ausdrücke, um die Referenzierung von Konstanten zu erleichtern (der Compiler berechnet konstante Ausdrücke vorab).
4. abnormal
Ausnahmen werden nur für eine einzige echte Fehlerbedingung verwendet, sodass das Auslösen einer Ausnahme und das Ausführen eines Catch-Blocks teuer sind (hauptsächlich aufgrund der Erstellung eines Snapshots des Thread-Stacks beim Erstellen einer Ausnahme).
Eine Ausnahme wird nur ausgelöst, wenn die Bedingung wirklich außergewöhnlich ist. Um eine Ausnahme auszulösen, erstellen Sie zunächst ein neues Objekt.
Der Konstruktor der Throwable-Schnittstelle ruft die native Methode namens fillInStackTrace() auf. Die Methode fillInStackTrace() überprüft den Stapel und sammelt Informationen zur Anrufverfolgung.
Immer wenn eine Ausnahme ausgelöst wird, muss die VM den Aufrufstapel anpassen, da während der Verarbeitung ein neues Objekt erstellt wird.
Ausnahmen sollten nur zur Fehlerbehandlung und nicht zur Steuerung des Programmablaufs verwendet werden.
Nehmen Sie Compiler- und Laufzeitoptimierungen vor, indem Sie mehrere Methodenaufrufe in einem Try/Catch-Block platzieren, anstatt mehrere Try/Catch-Blöcke für jeden Methodenaufruf zu implementieren
try{ Some.method1(); //Difficut for java1.4 }catch(method1Exception e){ Ausnahme behandeln
1 // um diesen Code zu optimieren } try{ Some.method2(); //Difficut für java1.4 }catch(method2Exception e){ Ausnahme behandeln
2 // um diesen Code zu optimieren } try{ Some.method3(); //Difficut für java1.4 }catch(method3Exception e){ Ausnahme behandeln
3 // um diesen Code zu optimieren
}
sollte wie folgt geschrieben werden:
try{ Some.method1(); Some.method3(); //Difficut für java1.4 }catch(method1Exception e){ handle Ausnahme 1 }catch(method2Exception e){ handle Ausnahme 2 }catch( method3Exception e){ Ausnahme 3 behandeln }
5. Maßstab
Beachten Sie, dass alle diese Tipps je nach Plattform und virtueller Maschine unterschiedlich sind
Beispiel: In einigen Servlet-Containern ist es schneller, Bytes über einen OutputStream auszugeben
2. In anderen Containern ist die Ausgabe von Zeichen über einen PrintWriter schneller
Diese Tipps beschreiben die tragbarsten Empfehlungen
Möglicherweise müssen Sie einige Benchmarks durchführen, um festzustellen, was auf Ihrer Plattform am schnellsten ist
6. Erstellen Sie eine Instanz einer Klasse, ohne das Schlüsselwort new zu verwenden
Wenn Sie eine Instanz einer Klasse mit dem Schlüsselwort new erstellen, werden alle Konstruktoren in der Konstruktorkette automatisch aufgerufen.
Aber wenn ein Objekt die Cloneable-Schnittstelle implementiert, können wir seine clone()-Methode aufrufen. Die Methode clone() ruft keine Klassenkonstruktoren auf.
Wenn Sie bei Verwendung von Design Pattern den Factory-Modus zum Erstellen eines Objekts verwenden, ist es sehr einfach, mit der clone()-Methode eine neue Objektinstanz zu erstellen.
Das Folgende ist beispielsweise eine typische Implementierung des Factory-Musters:
public static Credit getNewCredit() { return new Credit( }
Nach der Optimierung:
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() { return (Credit) BaseCredit.clone();}
Die oben genannten Ideen sind auch für die Array-Verarbeitung nützlich.
7. Verwenden Sie nicht blockierende E/A
JDKs mit niedrigeren Java-Versionen unterstützen keine nicht blockierenden I/O-APIs. Um E/A-Blockierungen zu vermeiden, erstellen einige Anwendungen eine große Anzahl von Threads (in besseren Fällen wird ein Pufferpool verwendet). Diese Technik kommt in vielen Anwendungen zum Einsatz, die gleichzeitige E/A-Streams unterstützen müssen, wie z. B. Webserver, Angebots- und Auktionsanwendungen usw. Das Erstellen von Java-Threads erfordert jedoch einen erheblichen Aufwand.
Mit JDK 1.4 wurde eine nicht blockierende I/O-Bibliothek (java.nio) eingeführt. Wenn Ihre Anwendung eine ältere Version des JDK erfordert, gibt es ein Paket, das nicht blockierende E/A unterstützt.
8. Initialisieren Sie Variablen nicht wiederholt
Standardmäßig initialisiert Java beim Aufruf des Konstruktors einer Klasse Variablen mit bestimmten Werten: Alle Objekte werden auf Null gesetzt, Ganzzahlvariablen (Byte, Short, Int, Long) werden auf 0 gesetzt und Float- und Double-Variablen werden auf gesetzt 0,0, der logische Wert wird auf false gesetzt.
Dies sollte insbesondere dann beachtet werden, wenn eine Klasse von einer anderen Klasse abgeleitet ist, da beim Erstellen eines Objekts mit dem Schlüsselwort new automatisch alle Konstruktoren in der Konstruktorkette aufgerufen werden.
9. Versuchen Sie, den endgültigen Modifikator der Klasse anzugeben
Klassen mit dem finalen Modifikator werden nicht abgeleitet. In der Java-Kern-API gibt es viele Beispiele für die Anwendung von final, z. B. java.lang.String. Durch die Angabe von final für die String-Klasse wird verhindert, dass Benutzer die Methode length() überschreiben.
Wenn eine Klasse außerdem als final gekennzeichnet ist, sind alle Methoden der Klasse final. Der Java-Compiler sucht nach Möglichkeiten, alle endgültigen Methoden zu integrieren (dies hängt von der jeweiligen Compiler-Implementierung ab). Dadurch kann die Leistung um durchschnittlich 50 % verbessert werden.
10. Verwenden Sie nach Möglichkeit lokale Variablen
Die beim Aufruf der Methode übergebenen Parameter und die beim Aufruf erstellten temporären Variablen werden im Stapel (Stack) gespeichert, was schneller ist. Andere Variablen wie statische Variablen, Instanzvariablen usw. werden im Heap erstellt und sind langsamer. Darüber hinaus können lokale Variablen je nach Compiler/JVM weiter optimiert werden. Siehe Wo immer möglich Stack-Variablen verwenden.
11. Multiplikation und Division
Betrachten Sie den folgenden Code:
for (val = 0; val < 100000; val +=5) { alterX = val * 8;
Nach der Optimierung:
for (val = 0; val <100000; val += 5) { alterX = val << 3;
Der geänderte Code führt nicht mehr die Operation des Multiplizierens mit 8 durch, sondern verwendet stattdessen die äquivalente Operation des Verschiebens von 3 Bits nach links. Jede Verschiebung um 1 Bit nach links entspricht einer Multiplikation mit 2. Dementsprechend entspricht eine Verschiebung um 1 Bit nach rechts einer Division durch 2. Es ist erwähnenswert, dass der Umschaltvorgang zwar schnell ist, der Code jedoch möglicherweise schwieriger zu verstehen ist. Daher ist es am besten, einige Kommentare hinzuzufügen.
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() {return (Credit) BaseCredit.clone();}