final y otras palabras clave de Java - 1

"¡Hola, amigo!"

"¡Hola, Bilaabo!"

“Hoy os voy a hablar de varias palabras clave en Java. Pero empezaré por la más interesante: la palabra clave final ” .

"Puede usar la palabra clave final al declarar una variable, método o clase".

"¿Y por qué necesitamos la final?"

"Es bastante simple. Si marcamos una variable como final, se vuelve inmutable:"

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

"Veo."

"Si marcamos un método como final, está prohibido anular el método en las clases derivadas:"

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

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

"Ya veo. Pero, ¿por qué necesitarías prohibir anular un método?"

"Bueno, como ejemplo, supongamos que un programador ha escrito mucho código importante en un método y quiere garantizar que todas las clases que heredan su clase tendrán el comportamiento especificado".

"Y finalmente, el tercer uso".

"Si marcamos una clase con la palabra clave final, entonces no se puede heredar".

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

"¿Y por qué evitaríamos que una clase sea heredada?"

"Debe comprender que no evitamos que la herencia sea molesta, sino por el bien de la seguridad y la integridad del código. Si la herencia de clase no está prohibida, entonces la implicación es que está permitida. Y que el código escrito por la clase designer funcionará correctamente para los objetos de esta clase, así como para los objetos de cualquier clase derivada".

"Pero si un desarrollador se da cuenta de que incluso pequeños cambios en su clase harán que todo deje de funcionar como se esperaba, entonces es mejor prohibir la herencia".

"Por ejemplo, la clase String se declara como final, al igual que todos los tipos primitivos: Integer, Boolean, Double, Character..."

"Ah, lo entiendo. La clase String se creó como una clase inmutable y si de repente fueran mutables, muchas cosas dejarían de funcionar".

“Pues casi. Digámoslo así: todo funcionaría casi como antes, pero a veces habría errores que serían muy difíciles de encontrar y entender. Entonces, en algunos casos, heredar clases o métodos no es realmente un pecado, pero prohibirlo significa menos errores para detectar más tarde".

"¿Dónde más puedes usar final?"

"Puede usar los parámetros finales antes de la función y antes de las variables en un método. Aquí hay un ejemplo:"

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

"¿Y cuál es el punto de eso?"

"Bueno, hay dos. Primero, declaramos una variable como final si queremos decirles a otros desarrolladores que este valor es una constante específica, y no solo una variable".

Por ejemplo, queremos calcular el impuesto sobre las ventas en función de un precio:

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

"Y segundo, necesitamos este tipo de variable cuando escribimos clases internas locales o anónimas. Les hablaré sobre este tipo de clases pronto. Pero no hoy".

"Está bien, hasta ahora no ha habido nada demasiado complicado".

"Tenga en cuenta que solo la variable se vuelve inmutable, no un objeto al que podría referirse. El objeto aún se puede cambiar".

"En realidad estaba a punto de preguntar sobre eso. ¿Y no hay forma de hacer que el objeto no se pueda cambiar?"

"No, a menos que escribas una clase inmutable".

"Tenga en cuenta que debido a que el valor de una variable final no se puede cambiar, debe asignar su valor inicial de inmediato".

Este código compilará Este código no compilará
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()
 {
 }
}

"Pero, dicho esto, Java le permite retrasar la inicialización de las variables finales de una clase hasta el constructor".

Este código compilará Este código no compilará
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;
 }
}

"Además, diferentes constructores pueden inicializar variables finales con diferentes valores. Esto es muy conveniente:"

Este código compilará
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;
 }
}

"Ese fue un tema realmente interesante, y absolutamente todo tiene sentido. ¡Gracias, Bilaabo!"