Casi in cui vengono creati oggetti non necessari
Utilizzo di new String()
Le stringhe a, b e c avranno tutte la stringa "hi". Tuttavia, poiché gli indirizzi a cui fanno riferimento queste tre stringhe sono tutti diversi, si verifica uno spreco di risorse dovuto all'allocazione di memorie diverse per gli stessi dati.
<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa53d14aa-6abf-40f0-8441-435647d172fa%2FUntitled.png?table=block&id=f168859c-367c-4924-a4c6-5e04788fab67&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/1146;" width="2000" height="1146"></span>
Pertanto, quando si dichiara una stringa, è necessario utilizzare un letterale invece della parola chiave new.
Il codice sorgente precedente utilizza una sola istanza. Inoltre, utilizzando questo metodo, si garantisce che tutti i codici che utilizzano il letterale della stringa "hi" all'interno della stessa JVM riutilizzino lo stesso oggetto. Ciò è dovuto a una caratteristica del pool di costanti di Java.
Utilizzo di new Boolean()
Nel codice precedente, viene creata un'istanza di Boolean tramite un costruttore che accetta una stringa come parametro. Boolean può essere solo true o false, e creare un'istanza ogni volta è uno spreco di memoria. Pertanto, è meglio utilizzare il metodo di fabbrica statico Boolean.valueOf().
Utilizzo di String.matches()
Se il costo di creazione è elevato, è consigliabile memorizzare nella cache e riutilizzare gli oggetti, ma non sempre è possibile conoscere il costo degli oggetti che creiamo. Ad esempio, se si desidera scrivere un metodo per verificare se una stringa data è un numero romano valido, è più semplice utilizzare un'espressione regolare come segue.
Tuttavia, String.matches() è un metodo problematico dal punto di vista delle prestazioni. L'istanza di Pattern per le espressioni regolari creata internamente da questo metodo viene utilizzata una volta e quindi scartata, diventando immediatamente un candidato per la garbage collection. Tuttavia, maggiore è la frequenza con cui viene utilizzata la stessa espressione regolare, maggiore è il costo di creazione e smaltimento della stessa istanza di Pattern. Pertanto, è consigliabile memorizzare nella cache l'istanza di Pattern in anticipo e riutilizzarla ogni volta che viene chiamato il metodo isRomanNumeral().
Nota
In tutti gli esempi precedenti, quando abbiamo memorizzato nella cache oggetti non necessari, li abbiamo resi immutabili. Questo perché è sicuro riutilizzarli in questo modo. Tuttavia, ci sono casi in cui riutilizzare un oggetto immutabile va contro l'intuizione.
Un adattatore (vista) è un oggetto che delega le operazioni effettive a un oggetto di back-end e funge da seconda interfaccia. Poiché un adattatore deve gestire solo l'oggetto di back-end, è sufficiente creare un solo adattatore per ogni oggetto di back-end.
Ad esempio, il metodo keySet() dell'interfaccia Map restituisce una vista Set contenente tutte le chiavi all'interno dell'oggetto Map. Gli utenti potrebbero pensare che ogni volta che viene chiamato il metodo keySet(), venga creata una nuova istanza di Set, ma in realtà, osservando l'implementazione JDK, si vede che viene restituita sempre la stessa istanza di Set variabile.
Questo perché tutte le funzioni eseguite dall'istanza Set restituita sono le stesse, indipendentemente dal fatto che sia variabile, e tutte le istanze Set rappresentano l'istanza Map. Pertanto, non importa se keySet() crea più viste oggetto, ma non c'è bisogno di farlo, né offre alcun vantaggio.
Pertanto, se modifichiamo l'istanza names1, l'istanza names2 verrà influenzata allo stesso modo.
Tuttavia, personalmente credo che il valore restituito dal metodo keySet() debba essere restituito come un nuovo oggetto ogni volta utilizzando la copia difensiva. Se l'istanza Set ricevuta dal metodo keySet() è utilizzata anche in altri punti e c'è del codice che ne modifica lo stato, non si può più essere certi dello stato dell'istanza Set e dell'istanza Map in uso.
Inoltre, a meno che l'ambiente non utilizzi keySet() eccessivamente, la creazione di un'interfaccia Set ogni volta non ha un impatto significativo sulle prestazioni. Personalmente credo che sia meglio rendere l'interfaccia Set immutabile per garantire la stabilità e la manutenibilità del codice.
Autoboxing
L'autoboxing è una tecnica che converte automaticamente i tipi primitivi nei tipi wrapper quando i programmatori li mescolano. Tuttavia, l'autoboxing non elimina completamente la distinzione tra tipi primitivi e tipi wrapper, ma la rende meno evidente.
Logicamente, non ci sono problemi, ma il codice è molto inefficiente dal punto di vista delle prestazioni. La causa di ciò risiede nel tipo di sum e nel tipo di i all'interno del ciclo for.
Il tipo di sum è Long e il tipo di i è long. Ciò significa che ogni volta che i, che è di tipo long, viene aggiunto a sum durante l'esecuzione del ciclo, viene creata una nuova istanza di Long. Di conseguenza, è meglio utilizzare i tipi primitivi rispetto ai tipi wrapper e prestare attenzione per evitare l'autoboxing non intenzionale.
Parti da non fraintendere
Non bisogna fraintendere il consiglio di evitare la creazione di oggetti non necessari come "evitare la creazione di oggetti perché il loro costo è elevato".
In particolare, nelle JVM moderne, la creazione e lo smaltimento di piccoli oggetti creati inutilmente non rappresentano un grande carico. Pertanto, a meno che non si tratti di oggetti con un costo elevato come le connessioni al database, non creare pool di oggetti personalizzati.
Inoltre, è importante ricordare che i danni derivanti dal riutilizzo di un oggetto in un caso in cui è necessaria una copia difensiva sono molto maggiori rispetto a quelli derivanti dalla creazione ripetuta di oggetti non necessari. Gli effetti collaterali della creazione ripetuta influiscono solo sulla forma e sulle prestazioni del codice, mentre l'errore di copia difensiva porta direttamente a bug e problemi di sicurezza.
Commenti0