final e altre parole chiave Java - 1

"Ciao, Amico!"

"Ciao Bilaabo!"

"Oggi ti parlerò di diverse parole chiave in Java. Ma inizierò con la più interessante: la parola chiave finale. "

"Puoi usare la parola chiave final quando dichiari una variabile, un metodo o una classe."

"E perché abbiamo bisogno di finale?"

"È piuttosto semplice. Se contrassegniamo una variabile come finale, diventa immutabile:"

final int i = 5;
i++; //Compilation error: the value of i cannot be changed.

"Vedo."

"Se contrassegniamo un metodo come final, è vietato eseguire l'override del metodo nelle classi derivate:"

class Cat
{
 public final String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat
{
 public String getName() //Compilation error: overriding the getName()
 {
  return "tiger";
 }
}

"Capisco. Ma perché dovresti proibire l'override di un metodo?"

"Bene, ad esempio, supponiamo che un programmatore abbia scritto molto codice importante in un metodo e voglia garantire che tutte le classi che erediteranno la sua classe avranno il comportamento specificato."

"E infine, il terzo uso."

"Se contrassegniamo una classe con la parola chiave final, allora non può essere ereditata."

public final class Cat
{
 public String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat //Compilation error: the Cat class cannot be
{
 public String getName()
 {
  return "tiger";
 }
}

"E perché dovremmo impedire che una classe venga ereditata?"

"Dovresti capire che non impediamo che l'ereditarietà sia fastidiosa, ma piuttosto per motivi di sicurezza e integrità del codice. Se l'ereditarietà di classe non è proibita, allora l'implicazione è che è consentita. E che il codice scritto dalla classe designer funzionerà correttamente per gli oggetti di questa classe così come per gli oggetti di qualsiasi classe derivata."

"Ma se uno sviluppatore si rende conto che anche piccole modifiche alla sua classe faranno sì che tutto smetta di funzionare come previsto, allora è meglio vietare l'ereditarietà".

"Ad esempio, la classe String è dichiarata final, così come tutti i tipi primitivi: Integer, Boolean, Double, Character…"

"Ah, capito. La classe String è stata creata come una classe immutabile e se fossero improvvisamente mutabili, molte cose smetterebbero di funzionare."

"Beh, quasi. Mettiamola così: tutto funzionerebbe quasi come prima, ma a volte ci sarebbero errori che sarebbero molto difficili da trovare e capire. Quindi, in alcuni casi, ereditare classi o metodi non è proprio un peccato, ma proibirlo significa meno errori da rilevare in seguito."

"Dove altro puoi usare final?"

"È possibile utilizzare i parametri della funzione final before e le variabili before in un metodo. Ecco un esempio:"

public void setName(final String name)
{
 final String displayName = "Mr."+ name;
  …
 this.name = displayName;
}

"E che senso ha?"

"Beh, ce ne sono due. Primo, dichiariamo una variabile come finale se vogliamo dire agli altri sviluppatori che questo valore è una costante specifica, e non solo una variabile."

Ad esempio, vogliamo calcolare l'imposta sulle vendite in base a un prezzo:

public int getPriceNDS()
{
 final int NDS = 20;
 return this.price * NDS / 200;
}

"E secondo, abbiamo bisogno di questo tipo di variabile quando scriviamo classi interne locali o anonime. Presto vi parlerò di questi tipi di classi. Ma non oggi."

"Va bene, finora non c'è stato niente di troppo complicato."

"Si prega di notare che solo la variabile diventa immutabile, non un oggetto a cui potrebbe fare riferimento. L'oggetto può ancora essere modificato."

"In realtà stavo proprio per chiedertelo. E non c'è modo di rendere l'oggetto immutabile?"

"No, a meno che tu non scriva una classe immutabile."

"Si noti che poiché il valore di una variabile finale non può essere modificato, è necessario assegnarne immediatamente il valore iniziale."

Questo codice verrà compilato Questo codice non verrà compilato
class Home
{
 private final int width = 200;
 private final int height = 100;

 public Home()
 {
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
 }
}

"Ma, detto questo, Java ti consente di ritardare l'inizializzazione delle variabili finali di una classe fino al costruttore."

Questo codice verrà compilato Questo codice non verrà compilato
class Home
{
 private final int width = 200;
 private final int height;

 public Home()
 {
  height = 100;
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
 }
}

"Inoltre, diversi costruttori possono inizializzare variabili finali con valori diversi. Questo è abbastanza conveniente:"

Questo codice verrà compilato
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
  width = 200;
 }

 public Home(int width)
 {
  this.height = 300;
  this.width = width;
 }

 public Home(int width, int height)
 {
  this.height = height;
  this.width = width;
 }
}

"Era un argomento davvero interessante, e assolutamente tutto ha un senso. Grazie, Bilaabo!"