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

Dit is een door AI vertaalde post.

제이온

[Effectieve Java] Item 6. Vermijd onnodige objectcreatie

Selecteer taal

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

Samengevat door durumis AI

  • Het maken van string- of Boolean-instanties met behulp van het sleutelwoord 'new' is een verspilling van geheugen, dus het is beter om literals te verklaren of de Boolean.valueOf()-methode te gebruiken.
  • De String.matches()-methode gebruikt reguliere expressies, wat kan leiden tot prestatieproblemen, dus het is beter om Pattern-instanties te cachen en opnieuw te gebruiken.
  • Wanneer een weergaveobject wordt geretourneerd, zoals de keySet()-methode, is het veiliger om een nieuw object te retourneren met behulp van een beschermende kopie.

Wanneer onnodige objecten worden gemaakt

Gebruik van `new String()`

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


De strings a, b en c bevatten allemaal de string "hi". Echter, de adressen die deze drie strings refereren zijn allemaal verschillend. Dit resulteert in verspilling, aangezien er verschillende geheugen wordt toegewezen voor dezelfde data.


Untitled


Daarom moet je bij het declareren van strings geen gebruik maken van het `new` keyword, maar moet je gebruik maken van een literal.


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


De bovenstaande code gebruikt slechts één instantie. Bovendien zorgt deze manier ervoor dat alle code in dezelfde JVM die de "hi" string literal gebruikt, hetzelfde object hergebruikt. Dit komt door de eigenschap van de Java constante pool.


Gebruik van `new Boolean()`

De bovenstaande code maakt een Boolean instantie aan via een constructor die een string als parameter accepteert. Boolean kan alleen true of false zijn. Het creëren van een instantie voor elk geval is verspilling van geheugen. Het is daarom beter om de statische factory methode `Boolean.valueOf()` te gebruiken.



Gebruik van `String.matches()`

Het is een goed idee om objecten te cachen als de creatiekosten hoog zijn. Het is echter niet altijd mogelijk om de kosten van de objecten die we maken te kennen. Stel dat we een methode willen maken die controleert of een gegeven string een geldig Romeins cijfer is. Het gebruik van een reguliere expressie is dan de eenvoudigste oplossing.


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})$");


Echter, `String.matches()` heeft een prestatieprobleem. De `Pattern` instantie die door deze methode wordt gemaakt voor reguliere expressies wordt eenmalig gebruikt en weggegooid. Dit betekent dat deze snel het doelwit wordt van garbage collection. Als deze reguliere expressie vaak wordt gebruikt, zullen er steeds meer `Pattern` instanties worden gemaakt en weggegooid. Het is daarom beter om de `Pattern` instantie te cachen en deze te hergebruiken bij elke oproep van de `isRomanNumeral()` methode.


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();
    }


Let op

In alle bovenstaande voorbeelden hebben we, bij het cachen van onnodige objecten, ervoor gezorgd dat deze onveranderlijk zijn. Dit is nodig om er zeker van te zijn dat ze veilig te hergebruiken zijn. Er zijn echter situaties waarin dit in tegenspraak is met de intuïtie om onveranderlijke objecten te hergebruiken.


Een adapter (view) is een object dat de daadwerkelijke bewerkingen delegeert aan een achterliggend object en zelf dient als een tweede interface. Een adapter hoeft alleen het achterliggende object te beheren, dus er kan voor elk achterliggend object slechts één adapter worden gemaakt.


De `keySet()` methode van de `Map` interface geeft bijvoorbeeld een `Set` view terug die alle sleutels in het `Map` object bevat. Gebruikers kunnen denken dat er bij elke oproep van de `keySet()` methode een nieuw `Set` instantie wordt aangemaakt. Maar als je kijkt naar de daadwerkelijke JDK-implementatie, wordt er steeds dezelfde variabele `Set` instantie teruggegeven.


Dit komt omdat alle `Set` instanties, ook al zijn ze variabel, dezelfde functionaliteit hebben en alle `Set` instanties het `Map` object vertegenwoordigen. Het is daarom niet erg om meerdere view-objecten te maken met `keySet()`, maar het is ook niet nodig en biedt geen voordeel.


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
    }


Als je `names1` instantie aanpast, zoals in het bovenstaande voorbeeld, zal `names2` instantie ook worden beïnvloed.


Persoonlijk denk ik dat de `keySet()` methode een defensieve kopie moet gebruiken en bij elke oproep een nieuw object moet teruggeven. Als de `Set` instantie die je met de `keySet()` methode ontvangt, ook ergens anders wordt gebruikt en er code is die de status van deze instantie verandert, weet je niet zeker wat de huidige status is van de `Set` instantie en het `Map` object.


Bovendien, tenzij je `keySet()` te veel gebruikt, zal het creëren van de `Set` interface bij elke oproep geen significante invloed hebben op de prestaties. Het is beter om de `Set` interface onveranderlijk te maken om stabiele onderhoudbaarheid te garanderen.


Auto-boxing

Auto-boxing is een techniek die het mogelijk maakt dat de programmeur primitieve typen en wrapper-typen door elkaar gebruikt. De conversie tussen de typen wordt dan automatisch uitgevoerd. Auto-boxing maakt de scheiding tussen primitieve typen en wrapper-typen echter niet volledig weg.


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


Logisch gezien is er geen probleem, maar prestatiegericht gezien is de code zeer inefficiënt. Dit komt door het type van `sum` en het type van `i` in de `for`-lus.


`sum` is van het type `Long` en `i` is van het type `long`. Dat wil zeggen dat `i`, van het type `long`, elke keer als het door de lus gaat en wordt opgeteld bij `sum`, een nieuwe `Long` instantie zal creëren. Dit resulteert in het creëren van nieuwe `Long` instanties die niet worden gebruikt. Het is daarom belangrijk om te zorgen dat de typen in je code consistent zijn om onbedoelde auto-boxing te voorkomen.


Misverstanden

Het vermijden van onnodige objectcreatie moet niet worden gezien als een kwestie van het vermijden van objectcreatie omdat de creatiekosten hoog zijn.


Vooral in moderne JVM's is het creëren en verzamelen van kleine objecten die niet worden gebruikt, geen zware taak. Het is daarom niet nodig om een aangepaste objectpool te maken, tenzij het gaat om objecten met hoge kosten, zoals database verbindingen.


Houd er bovendien rekening mee dat de schade die wordt veroorzaakt door het hergebruiken van objecten in een situatie waar een defensieve kopie nodig is, veel groter is dan de schade die wordt veroorzaakt door het herhaaldelijk creëren van objecten die niet nodig zijn. De nadelen van herhaalde creatie hebben alleen invloed op de codevorm en de prestaties, maar het mislukken van een defensieve kopie leidt tot bugs en beveiligingsproblemen.


Bronnen

제이온
제이온
제이온
제이온
[Effectieve Java] Item 2. Overweeg een bouwer als je constructor veel parameters heeft Het gebruik van het builder-patroon bij het maken van objecten met veel parameters maakt de code duidelijker en gemakkelijker leesbaar. Creëer een builder-object met vereiste parameters en stel optionele parameters in met setter-methoden, en roep de build

27 april 2024

[Effectieve Java] Item 5. Gebruik afhankelijke objectinjectie in plaats van resources expliciet te noemen Wanneer een klasse afhankelijk is van externe resources, is het gebruik van singletons en statische utility-klassen af te raden. Door afhankelijke objectinjectie te gebruiken, kunt u de flexibiliteit, herbruikbaarheid en testbaarheid van de klasse verbete

28 april 2024

[Java] Reflectie concept en gebruik Reflectie is een API die ondersteuning biedt om toegang te krijgen tot klasse-informatie tijdens de uitvoering van een Java-programma, zodat klassen kunnen worden gemanipuleerd. Tijdens runtime kunnen klassen worden gemaakt en toegang tot velden en method

25 april 2024

[Javascript] Object-structuur (V8) Het JavaScript Object wordt in de V8-engine geoptimaliseerd als een structuur afhankelijk van de toestand en werkt als een Fast-modus en een Dictionary-modus die als een hashmap werkt. De Fast-modus is snel met keys en waarden in een bijna vaste vorm, maa
곽경직
곽경직
곽경직
곽경직
곽경직

18 maart 2024

Hoe Rust concurrency-fouten voorkomt Rust is een krachtige taal die de uitdagingen van concurrency-programmeren aanpakt. Door het type-systeem en eigendomsmodel is het veilig om gegevens tussen threads te verzenden en te delen. Met behulp van interne veranderlijkheidspatronen zoals Mutex, Ch
곽경직
곽경직
곽경직
곽경직
곽경직

28 maart 2024

[Concurrency] Atomaire bewerking: Memory Fence en Memory Ordering Deze blogpost bespreekt hoe geheugensorde te overwegen in atomaire bewerkingen en het belang van de Ordering-opties. We bespreken verschillende Ordering-opties zoals Relaxed, Acquire, Release, AcqRel, SecCst, inclusief een beschrijving van de voor- en nad
곽경직
곽경직
곽경직
곽경직
곽경직

12 april 2024

3 dingen die ik wil zeggen tegen individuele beleggers die voor het eerst aandelen kopen Dit is advies over waardebeleggingsstrategieën en een positieve mentaliteit voor individuele beleggers die voor het eerst aandelen kopen. Waardebeleggen is een strategie waarbij je op korte termijn kansen op marktmisprijzen koopt en op lange termijn wacht
고집스런가치투자
고집스런가치투자
고집스런가치투자
고집스런가치투자

3 april 2024

[Niet-major, overleven als ontwikkelaar] 14. Samenvatting van veelgestelde technische interviewvragen voor beginnende ontwikkelaars Deze gids is bedoeld om beginnende ontwikkelaars te helpen met de voorbereiding op technische interviews. Het behandelt concepten die vaak ter sprake komen tijdens interviews, zoals het hoofdgeheugengebied, gegevensstructuren, RDBMS en NoSQL, procedurele
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 april 2024

[Niet-technische, ontwikkelen voor een levensonderhoud] 16. Tips voor het maken van een portfolio voor beginnende ontwikkelaars Beginnende ontwikkelaars (met name niet-technische) moeten bij het maken van een portfolio niet alleen hun vaardigheden, maar ook de ontwikkelde diensten of functies duidelijk beschrijven. Bijvoorbeeld, voor een "baanzoekersgemeenschap" project, moet je c
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 april 2024