JavaRush /Java Blog /Random-IT /Pausa caffè #134. Cosa evitare quando si scrive codice Ja...

Pausa caffè #134. Cosa evitare quando si scrive codice Java. Come vengono utilizzati final, final e finalize in Java

Pubblicato nel gruppo Random-IT

Cosa evitare quando si scrive codice Java

Fonte: Medium Portiamo alla vostra attenzione un articolo che elenca gli errori comuni che gli sviluppatori commettono durante la scrittura del codice Java. Pausa caffè #134.  Cosa evitare quando si scrive codice Java.  Come vengono utilizzati final, final e finalize in Java - 1

Utilizzando Enum.values

Il fatto che questo fosse considerato un bug mi ha colto di sorpresa poiché utilizzavo Enum.values ​​regolarmente . Il problema qui è che Enum.values() dovrebbe essere un elenco immutabile per specifica. Per fare ciò, deve restituire una nuova istanza dell'array con i valori enum ogni volta che viene chiamato.
public enum Fruits {
    APPLE, PEAR, ORANGE, BANANA;

    public static void main(String[] args) {
        System.out.println(Fruits.values());
        System.out.println(Fruits.values());
    }
}
// output
// [Lcom.test.Fruits;@7ad041f3
// [Lcom.test.Fruits;@251a69d7
Ci sono due oggetti separati in memoria qui, quindi potrebbe non sembrare un grosso problema. Ma se usi Fruit.values() durante l'elaborazione di una richiesta e hai un carico elevato, ciò può portare a problemi di memoria. Puoi risolvere facilmente questo problema introducendo una variabile finale statica privata VALUES per la memorizzazione nella cache.

Passaggio di parametri facoltativi come parametro del metodo

Considera il seguente codice:
LocalDateTime getCurrentTime(Optional<ZoneId> zoneId) {
    return zoneId.stream()
        .map(LocalDateTime::now)
        .findFirst()
        .orElse(LocalDateTime.now(ZoneId.systemDefault()));
}
Passiamo il parametro opzionale zoneId e, in base alla sua presenza, decidiamo se dare l'ora nel fuso orario del sistema oppure utilizzare il fuso specificato. Tuttavia, questo non è il modo corretto di lavorare con Optional. Dovremmo evitare di usarli come parametro e utilizzare invece l'overload del metodo.
LocalDateTime getCurrentTime(ZoneId zoneId) {
  return LocalDateTime.now(zoneId);
}

LocalDateTime getCurrentTime() {
  return getCurrentTime(ZoneId.systemDefault());
}
Il codice che vedi sopra è molto più facile da leggere ed eseguire il debug.

Utilizzando StringBuilder

Le stringhe in Java sono immutabili. Ciò significa che una volta creati non sono più modificabili. La JVM mantiene un pool di stringhe e, prima di crearne uno nuovo, chiama il metodo String.intern() , che restituisce un'istanza dal pool di stringhe corrispondente al valore, se ne esiste uno. Diciamo che vogliamo creare una lunga stringa concatenando gli elementi al suo interno.
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
Recentemente ci è stato detto che si trattava di una pessima idea perché le versioni precedenti di Java facevano quanto segue:
  • nella riga 1 la stringa “start” viene inserita nello string pool e puntata da longString
  • la riga 2 aggiunge la stringa "startmiddle" al pool e punta ad essa con longString
  • alla riga 3 abbiamo “startmiddlemiddle”
  • nella riga 4 - “startmiddlemiddlemiddle”
  • e infine alla riga 5 aggiungiamo "startmiddlemiddlemiddleend" al pool e puntiamo longString ad esso
Tutte queste righe rimangono nel pool e non vengono mai utilizzate, con conseguente spreco di una grande quantità di RAM. Per evitare questo possiamo usare StringBuilder.
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
StringBuilder crea solo una stringa quando viene chiamato il metodo toString , eliminando così tutte le stringhe intermedie inizialmente aggiunte al pool. Tuttavia, dopo Java 5 questo viene fatto automaticamente dal compilatore , quindi è meglio usare la concatenazione di stringhe usando "+".

Utilizzo di wrapper primitivi quando non sono necessari

Consideriamo i due frammenti seguenti:
int sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
Integer sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
Il primo esempio viene eseguito sei volte più velocemente del secondo sul mio computer. L'unica differenza è che utilizziamo una classe wrapper Integer. Il modo in cui Integer funziona è che alla riga 3, il runtime deve convertire la variabile sum in un intero primitivo (unboxing automatico) e, una volta eseguita l'aggiunta, il risultato viene quindi racchiuso in una nuova classe Integer. (confezionamento automatico). Ciò significa che stiamo creando 1 milione di classi Integer ed eseguendo due milioni di operazioni di packaging, il che spiega il drammatico rallentamento. Le classi wrapper dovrebbero essere utilizzate solo quando devono essere archiviate in raccolte. Tuttavia, le versioni future di Java supporteranno raccolte di tipi primitivi, il che renderà i wrapper obsoleti.

Come vengono utilizzati final, final e finalize in Java

Fonte: Newsshare In questo articolo imparerai dove, quando e perché viene utilizzata la parola chiave Finalize e se vale la pena utilizzarla in Java. Imparerai anche le differenze tra finale, finalmente e finalizzare.

Dove viene utilizzato un blocco finale?

Il blocco last in Java viene utilizzato per ospitare parti importanti del codice come il codice di pulizia, la chiusura di un file o la chiusura di una connessione, ad esempio. Il blocco last viene eseguito indipendentemente dal fatto che venga lanciata un'eccezione o che venga gestita tale eccezione. A infine contiene tutte le istruzioni importanti indipendentemente dal fatto che si verifichi o meno un'eccezione.

Come si finalizza una variabile in Java?

Esistono 3 modi per inizializzare una variabile Java finale:
  • È possibile inizializzare una variabile finale quando viene dichiarata. Questo approccio è il più comune.
  • Una variabile finale vuota viene inizializzata in un blocco o costruttore inizializzatore di istanza.
  • Una variabile statica finale vuota viene inizializzata all'interno di un blocco statico.

Possiamo chiamare manualmente il metodo finalize in Java?

Il metodo finalize() non è necessario e non è consigliabile chiamarlo quando un oggetto esce dall'ambito. Perché non è noto in anticipo quando (o se) verrà eseguito il metodo finalize() . In generale, finalizzare non è il metodo migliore da utilizzare a meno che non ce ne sia una necessità specifica. A partire da Java 9 è deprecato.

Quando viene chiamato il metodo finalize?

Il metodo finalize() viene chiamato per eseguire la pulizia subito prima della garbage collection.

Qual è la differenza tra final,finalmente e finalize?

La differenza principale tra final, final e finalize è che final è un modificatore di accesso, final è un blocco nella gestione delle eccezioni e finalize è un metodo di una classe di oggetti.

È possibile sovrascrivere i metodi finali?

No, i metodi dichiarati final non possono essere sovrascritti o nascosti.

Possiamo usare try without catch?

Sì, è possibile avere un blocco try senza un blocco catch utilizzando un blocco final . Come sappiamo, il blocco finale verrà sempre eseguito anche se nel blocco try si verifica un'eccezione diversa da System.

Quali sono i metodi finali?

I metodi finali non possono essere sovrascritti o nascosti dalle sottoclassi. Vengono utilizzati per impedire che un comportamento imprevisto di una sottoclasse modifichi un metodo che potrebbe essere critico per la funzione o la coerenza della classe.

Un costruttore può essere definitivo?

I costruttori non potranno MAI essere dichiarati definitivi. Il tuo compilatore genererà sempre un errore come "modificatore finale non consentito". Finale quando applicato ai metodi significa che il metodo non può essere sovrascritto in una sottoclasse. I costruttori NON sono metodi regolari.

A cosa serve la parola chiave finalmente?

La parola chiave final viene utilizzata per creare un blocco di codice successivo a un blocco try. Il blocco infine viene sempre eseguito indipendentemente dal fatto che si verifichi un'eccezione. L'uso di un blocco final ti consente di eseguire qualsiasi istruzione di tipo unwind che desideri eseguire, indipendentemente da ciò che accade nel codice protetto.

A cosa serve, infine?

Un blocco final in Java è un blocco utilizzato per eseguire parti di codice come la chiusura di una connessione e altre. Il blocco finale in Java viene sempre eseguito indipendentemente dal fatto che l'eccezione venga gestita o meno. Pertanto, contiene tutte le istruzioni necessarie che devono essere stampate indipendentemente dal fatto che si verifichi o meno un'eccezione.

Perché il metodo Finalize è protetto?

Perché il modificatore di accesso al metodo finalize() è protetto? Perché non può essere pubblico? Non è pubblico perché non dovrebbe essere chiamato da nessun altro oltre alla JVM. Tuttavia, deve essere protetto in modo che possa essere sovrascritto dalle sottoclassi che devono definirne il comportamento.

Il metodo finalize viene sempre chiamato in Java?

Il metodo finalize viene chiamato quando un oggetto sta per essere sottoposto a Garbage Collection. Ciò può verificarsi in qualsiasi momento dopo che il documento diventa idoneo per la garbage collection. Si noti che è del tutto possibile che l'oggetto non venga mai sottoposto a Garbage Collection (e quindi finalize non venga mai chiamato).

Qual è la differenza tra lanciare e lanciare?

La parola chiave Throw viene utilizzata per generare intenzionalmente un'eccezione. La parola chiave Throws viene utilizzata per dichiarare una o più eccezioni, separate da virgole. Quando si utilizza Throw, viene lanciata solo un'eccezione.

Qual è la differenza tra le parole chiave try catch e aware?

Si tratta di due concetti diversi: un blocco catch viene eseguito solo se si verifica un'eccezione nel blocco try. Il blocco final viene sempre eseguito dopo il blocco try(-catch), indipendentemente dal fatto che sia stata lanciata o meno un'eccezione.

Possiamo finalmente usarlo senza provare in Java?

Un blocco finalmente deve essere associato a un blocco try, non è possibile utilizzare finalmente senza un blocco try. È necessario inserire in questo blocco quelle istruzioni che devono essere sempre eseguite.

Possiamo ereditare il metodo finale?

Il metodo finale è ereditato? Sì, il metodo finale viene ereditato, ma non è possibile sovrascriverlo.

Quale metodo non può essere sovrascritto?

Non è possibile eseguire l'override dei metodi statici perché l'override del metodo si basa sul collegamento dinamico in fase di esecuzione e i metodi statici vengono associati utilizzando il collegamento statico in fase di compilazione. Pertanto, non è possibile sovrascrivere i metodi statici.

Cosa succede se il metodo finale viene sovrascritto?

Un metodo finale dichiarato in una classe genitore non può essere sovrascritto da una classe figlia. Se proviamo a sovrascrivere l'ultimo metodo, il compilatore lancerà un'eccezione in fase di compilazione.

La parola chiave final e il metodo finalize funzionano allo stesso modo?

Non ci sono somiglianze nelle loro funzioni, ad eccezione dei nomi simili. La parola chiave finale può essere utilizzata con una classe, un metodo o una variabile in Java. Una classe finale non è estensibile in Java, un metodo finale non può essere sovrascritto e una variabile finale non può essere modificata.

Qual è la super parola chiave in Java?

La parola chiave super in Java è una variabile di riferimento utilizzata per fare riferimento all'oggetto immediato della classe genitore. Ogni volta che si istanzia una sottoclasse, viene creata in parallelo un'istanza della classe genitore, a cui fa riferimento la variabile di riferimento super. La parola chiave super può essere utilizzata per chiamare direttamente un metodo di una classe genitore.

Qual è la differenza tra le parole chiave statiche e finali?

La differenza principale tra le parole chiave static e final è che la parola chiave static viene utilizzata per definire un membro di una classe che può essere utilizzato indipendentemente da qualsiasi oggetto di quella classe. La parola chiave Final viene utilizzata per dichiarare una variabile costante, un metodo che non può essere sovrascritto e una classe che non può essere ereditata.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION