Ecco un esempio di codice Java che porta a uno spreco di memoria e alcuni problemi potenziali.

Il seguente metodo doSomeWork() può venir chiamato più volte da altre parti del programma che usano i servizi di Example. La variabile tmp, usata solo in doSomeWork(), è stata impostata come campo della classe, nel tentativo di “risparmiare” memoria.
Ma il risultato è esattamente l’opposto.

public class Example {

  /** Used only in {#doSomeWork()}. */
  private CustomClass tmp;

  /**
   * Called by some client.
   */
  public void doSomeWork() {
    tmp = new CustomClass();
    // some stuff...
  }

  // other methods...

}

Indipendendemente dall’implementazione di CustomClass (che può essere anche una classe presa da qualche libreria), l’oggetto tmp rimane allocato per tutto il ciclo di vita dell’istanza di Example, a meno di non impostarlo a null prima della chiusura (ma non vedo motivi per sobbarcarsi il lavoro che può essere fatto dalla virtual machine).

Inoltre quest’impostazione ha un grosso effetto collaterale: le istanze di Example sono thread-unsafe, dato che tmp diventa una variabile di stato e chiamate a doSomeWork() da thread diversi potrebbero accedervi contemporaneamente.

Secondariamente, si viola la separazione delle responsabilità all’interno della classe Example, perché tmp può essere usato anche da altri metodi (non va sottovalutato il rischio di errori che questo comporta).

Certamente migliore è la seguente impostazione:

public class Example {

  /**
   * Called by some client.
   */
  public void doSomeWork() {
    final CustomClass tmp = new CustomClass();
    // some stuff...
  }

  // other methods...

}

in cui la visibilità di tmp è correttamente limitata al suo metodo, è rispettata la thread-safety e anche il ciclo di vista delle istanze di CustomClass è limitato (possono venir raccolte dal Garbage Collector a fine metodo o anche prima). Come nota finale, volendo, la variabile può adesso essere dichiarata final.

Annunci