Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Dies ist ein von KI übersetzter Beitrag.

제이온

[Effektives Java] Artikel 6. Vermeiden Sie unnötige Objekterstellung

  • Schreibsprache: Koreanisch
  • Referenzland: Alle Länder country-flag

Sprache auswählen

  • Deutsch
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Von durumis AI zusammengefasster Text

  • Die Verwendung des Schlüsselworts "new" zum Erstellen von String- oder Boolean-Instanzen ist eine Verschwendung von Speicherplatz. Es ist daher besser, sie als Literale zu deklarieren oder die Methode Boolean.valueOf() zu verwenden.
  • Die Methode String.matches() verwendet reguläre Ausdrücke und kann daher zu Leistungsproblemen führen. Es ist empfehlenswert, Pattern-Instanzen zu cachen und wiederzuverwenden.
  • Wenn Methoden wie keySet() Sicht-Objekte zurückgeben, ist es sicherer, eine defensive Kopie zu verwenden, um ein neues Objekt zurückzugeben.

Wenn unnötige Objekte erstellt werden

Verwenden von new String()

String a = new String("hi");
String b = new String("hi");


Die Zeichenfolgen a, b und c erhalten alle die Zeichenfolge „hi“. Da die drei Zeichenfolgen jedoch auf unterschiedliche Adressen verweisen, wird für dieselben Daten unterschiedlicher Speicher zugewiesen, was zu Verschwendung führt.


Untitled


Daher sollten Sie bei der Deklaration von Zeichenfolgen nicht das Schlüsselwort new, sondern Literal verwenden.


String a = "hi";
String b = "hi";


Der obige Quellcode verwendet nur eine Instanz. Darüber hinaus wird durch die Verwendung dieser Methode sichergestellt, dass alle Codes innerhalb derselben JVM, die das Zeichenfolgenliteral „hi“ verwenden, dasselbe Objekt wiederverwenden. Dies ist auf die Funktion des Java-Konstantenpools zurückzuführen.


Verwenden von new Boolean()

Der obige Code erstellt eine Boolean-Instanz mithilfe des Konstruktors, der eine Zeichenfolge als Parameter entgegennimmt. Boolean kann nur true oder false sein, aber das Erstellen einer Instanz jedes Mal ist eine Verschwendung von Speicher. Daher ist es besser, die statische Factory-Methode Boolean.valueOf() zu verwenden.



Verwenden von String.matches()

Wenn die Erstellungskosten hoch sind, ist es eine gute Idee, sie zu cachen und wiederzuverwenden, aber wir kennen nicht immer die Kosten des von uns erstellten Objekts. Wenn wir beispielsweise eine Methode schreiben möchten, um zu überprüfen, ob eine gegebene Zeichenfolge eine gültige römische Zahl ist, ist es am einfachsten, reguläre Ausdrücke wie folgt zu verwenden.


public static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");


String.matches() ist jedoch eine Methode, die in Bezug auf die Leistung problematisch ist. Die Pattern-Instanz, die diese Methode intern für reguläre Ausdrücke erstellt, wird einmal verwendet und dann verworfen und ist sofort für die Garbage Collection vorgesehen. Je höher die Häufigkeit ist, mit der dieser reguläre Ausdruck wiederholt verwendet wird, desto höher sind die Kosten für die Erstellung und das Verwerfen derselben Pattern-Instanz. Daher ist es eine gute Idee, die Pattern-Instanz im Voraus zu cachen und diese Instanz bei jedem späteren Aufruf der isRomanNumeral()-Methode wiederzuverwenden.


public class RomanNumerals {

    private static final Pattern ROMAN = Pattern.compile(
        "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    public static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }


Hinweis

In allen obigen Beispielen wurde das unnötige Objekt beim Cachen zu einem unveränderlichen Objekt gemacht. Dies ist notwendig, damit es sicher wiederverwendet werden kann. Es gibt jedoch Fälle, die der Intuition widersprechen, ein unveränderliches Objekt wiederzuverwenden.


Ein Adapter (View) ist ein Objekt, das die eigentliche Arbeit an ein Backend-Objekt delegiert und selbst als zweite Schnittstelle fungiert. Der Adapter muss nur das Backend-Objekt verwalten, daher reicht es aus, für jedes Backend-Objekt einen Adapter zu erstellen.


Wenn Sie beispielsweise die keySet()-Methode der Map-Schnittstelle aufrufen, wird eine Set-View zurückgegeben, die alle Schlüssel im Map-Objekt enthält. Der Benutzer könnte denken, dass bei jedem Aufruf der keySet()-Methode eine neue Set-Instanz erstellt wird. Wenn Sie sich jedoch den tatsächlichen JDK-Implementierungsinhalt ansehen, wird jedes Mal dieselbe veränderliche Set-Instanz zurückgegeben.


Dies liegt daran, dass die zurückgegebenen Set-Instanzen zwar veränderlich sind, aber alle dieselbe Funktion ausführen und alle Set-Instanzen das Map-Objekt repräsentieren. Daher spielt es keine Rolle, ob keySet() mehrere View-Objekte erstellt, aber es gibt auch keine Notwendigkeit oder keinen Vorteil.


public class UsingKeySet {

    public static void main(String[] args) {
        Map menu = new HashMap<>();
        menu.put("Burger", 8);
        menu.put("Pizza", 9);

        Set names1 = menu.keySet();
        Set names2 = menu.keySet();

        names1.remove("Burger");
        System.out.println(names1.size()); // 1
        System.out.println(names2.size()); // 1
    }


Wenn Sie also die names1-Instanz wie oben ändern, wirkt sich dies auch auf die names2-Instanz aus.


Persönlich denke ich jedoch, dass der Rückgabewert der keySet()-Methode eine defensive Kopie verwenden sollte, um jedes Mal ein neues Objekt zurückzugeben. Wenn die über die keySet()-Methode empfangene Set-Instanz an anderer Stelle verwendet wird und es Code gibt, der den Zustand dieser Instanz ändert, kann man sich nicht auf den Wert der derzeit verwendeten Set-Instanz und der Map-Instanz verlassen.


Außerdem wirkt sich die wiederholte Erstellung der Set-Schnittstelle nicht negativ auf die Leistung aus, es sei denn, die keySet()-Methode wird übermäßig oft verwendet. Ich denke, es ist besser, die Set-Schnittstelle unveränderlich zu machen, um sie stabil zu warten.


Autoboxing

Autoboxing ist eine Technik, die es Programmierern ermöglicht, primitive Typen und Wrapper-Typen zu mischen und automatisch zwischen ihnen zu konvertieren. Autoboxing entfernt die Unterscheidung zwischen primitiven Typen und Wrapper-Typen jedoch nicht vollständig.


public static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    return sum;


Logisch ist alles in Ordnung, aber der Code ist in Bezug auf die Leistung sehr ineffizient. Der Grund dafür liegt im Typ von sum und im Typ von i innerhalb der for-Schleife.


Der Typ von sum ist Long, und i ist vom Typ long. Das heißt, wenn i vom Typ long während der Schleife iteriert und zu sum addiert wird, wird eine neue Long-Instanz erstellt. Daher sollten Sie eher primitive Typen als Wrapper-Typen verwenden und auf unbeabsichtigtes Autoboxing achten.


Was man nicht missverstehen sollte

Es sollte nicht einfach so verstanden werden, dass die Vermeidung unnötiger Objekterstellungen bedeutet, dass die Kosten für die Objekterstellung hoch sind und daher vermieden werden sollten.


Insbesondere in der heutigen JVM ist es keine Belastung, unnötig erstellte kleine Objekte zu erstellen und zu entsorgen. Daher sollten Sie keinen benutzerdefinierten Objektpool erstellen, es sei denn, es handelt sich um ein Objekt mit sehr hohen Kosten wie eine Datenbankverbindung.


Denken Sie außerdem daran, dass der Schaden, der durch die Wiederverwendung von Objekten entsteht, wenn eine defensive Kopie erforderlich ist, viel größer ist als der Schaden, der durch die wiederholte Erstellung unnötiger Objekte entsteht. Die Nebenwirkungen der wiederholten Erstellung wirken sich nur auf die Codeform und die Leistung aus, aber wenn eine defensive Kopie fehlschlägt, führt dies direkt zu Fehlern und Sicherheitsproblemen.


Quelle

제이온
제이온
제이온
제이온
[Effektives Java] Item 1. Statische Fabrikmethoden in Betracht ziehen Statische Fabrikmethoden sind eine flexible und effiziente Möglichkeit, Instanzen zu erstellen, anstatt Konstruktoren zu verwenden. Sie können benannt werden, Instanzen zurückgeben, die bestimmten Bedingungen entsprechen, und die Leistung durch Caching ve

27. April 2024

[Effektives Java] Punkt 5: Verwenden Sie Dependency Injection anstelle von expliziten Ressourcen Wenn eine Klasse von externen Ressourcen abhängt, sollten Singleton- und statische Utility-Klassen vermieden werden. Durch Dependency Injection können Sie die Flexibilität, Wiederverwendbarkeit und Testbarkeit der Klasse verbessern. Die Verwendung des Fac

28. April 2024

[Effektives Java] Artikel 2. Erwägen Sie einen Builder, wenn der Konstruktor viele Parameter hat Wenn Sie ein Objekt mit vielen Parametern erstellen, können Sie den Builder-Pattern verwenden, um den Code übersichtlicher und lesbarer zu machen. Erstellen Sie ein Builder-Objekt mit den erforderlichen Parametern, stellen Sie die optionalen Parameter mit

27. April 2024

[Javascript] Objektstruktur (V8) Das JavaScript-Objekt wird in der V8-Engine je nach Zustand als strukturierte, optimierte Fast-Mode oder als Hashmap-basierter Dictionary-Mode dargestellt. Der Fast-Mode ist schnell, wenn Schlüssel und Werte fast fixiert sind, aber bei der Hinzufügung neu
곽경직
곽경직
곽경직
곽경직
곽경직

18. März 2024

[Concurrency] Atomarer Vorgang: Memory Fence und Memory Ordering Dieser Blogbeitrag erklärt, wie bei atomaren Operationen die Reihenfolge im Speicher berücksichtigt wird, und die Bedeutung von Ordering-Optionen. Es werden verschiedene Ordering-Optionen wie Relaxed, Acquire, Release, AcqRel, SecCst erläutert und die Vor
곽경직
곽경직
곽경직
곽경직
곽경직

12. April 2024

Wie Rust Konsistenzfehler verhindert Rust ist eine leistungsstarke Sprache, die die Herausforderungen der konkurrenten Programmierung bewältigt. Dank des Typsystems und des Besitzmodells ist der Datenaustausch und die gemeinsame Nutzung zwischen Threads sicher. Durch Muster der internen Vari
곽경직
곽경직
곽경직
곽경직
곽경직

28. März 2024

[Nicht-Hauptfach, Überleben als Entwickler] 14. Zusammenfassung der häufigen technischen Vorstellungsgesprächsinhalte für Einsteiger Dieser Leitfaden ist für die Vorbereitung auf technische Vorstellungsgespräche für Einsteiger. Hauptspeicherbereich, Datenstrukturen, RDBMS und NoSQL, prozedurale und objektorientierte Programmierung, Überladen und Überschreiben, Seitenersatzzustände, Pro
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3. April 2024

[React Hook] useState Dieser Artikel enthält eine detaillierte Erklärung, warum der React useState-Hook bei einem Re-Rendering die gesamte Komponente erneut rendert, wie man Werte beibehält und wie die interne Implementierungsstruktur funktioniert. Durch die Analyse des ReactF
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

14. März 2024

Was ist Slot-Filling? Slot-Filling ist, wenn ein Chatbot wiederholt Fragen stellt, bis er alle notwendigen Informationen vom Benutzer erhalten hat. Zum Beispiel fragt ein Chatbot bei einer Kaffee Bestellung nach der Art, der Temperatur und der Größe, und beendet die Bestellung
꿈많은청년들
꿈많은청년들
Ein Bild mit der Aufschrift "Slot-Filling".
꿈많은청년들
꿈많은청년들

13. Mai 2024