Declaración y uso de constantes en Java. Uso del final en Java, datos final

En la sección anterior hablamos sobre variables y tipos en java y aprendimos cómo se declara una variable, cómo se le asigna un tipo de dato específico (primitivo o complejo). En esta sección hablaremos ya no tanto de "variables" sino más bien de constantes. Una constante desde el punto de vista de la programación es un dato cuyo valor no cambia durante la ejecución del programa, en otras palabras, una vez que a una constante se le asigna un valor, este no podrá ser modificado y permanecerá así durante toda la ejecución del programa.

Las constantes son útiles para datos o atributos para los cuales el valor no tiene por qué cambiar, por ejemplo, el número del documento de identidad de una persona, lo más normal es que dicho número no cambie o la fecha de nacimiento, una persona tiene una fecha de nacimiento única e invariable, por lo tanto por ejemplo un atributo "nacimiento" debería ser constante. Con esto podremos evitar modificaciones en nuestro sistema que puedan causar problemas durante la ejecución del mismo.

En esta sección no hablaremos únicamente sobre cómo hacer que un dato cualquiera no permanezca constante, sino también, veremos qué implicaciones tiene que una clase, un método y un atributo sean constantes (final). Comencemos:

Constantes en Java:

La palabra clave que java ha reservado para definir constantes es la palabra "final". En java es muy simple definir constantes, solo basta con ponerles el modificador final antes de la declaración del tipo. Al definir un dato como constante le podremos asignar un valor por primera vez y luego de eso no será posible cambiarle ese valor. Una vez inicializado el dato, este no podrá cambiar su valor de ninguna forma.

Modificador final en Java:

Tal como mencioné hace un momento el modificador final es la palabra reservada que Java definió para crear constantes. Veamos entonces la sintaxis general para definir un dato como constante en Java:

Datos constantes en Java

	
final tipo nombreVble = valor;
	

Como se puede apreciar la sintaxis es bastante sencilla, sin embargo hay que tener en cuenta algunas cosas: cuando vamos a declarar un dato cualquiera como final, debemos asignarle inmediatamente un valor, es decir debemos inicializarlo de inmediato, de lo contrario no podremos compilar nuestro código. En este punto debo hacer una aclaración, un dato cualquiera que se encuentre por ejemplo al interior del método main, debe ser inicializado de inmediato, sin embargo un atributo propio de una clase no necesariamente debe ser inicializado en el mismo momento que se declara dicho atributo, sino que puede ser inicializado también por un constructor, dando así la posibilidad de que cada objeto especifico tenga su propio valor constante, ingresa a continuacón para saber más sobre atributos y constructores. Vemos el ejemplo:

Atributos constantes en java

	
public class Constantes
{
	private final String atribConstante;
	//Notar que no ha sido inicializado
	
	//Constructor
	Constantes(String valor)
	{
		//Aquí se inicializó el atributo
		atribConstante = valor;
	}
}
	

En el código anterior, podemos apreciar entonces que en el caso de los atributos de una clase no es necesario inicializar dicho atributo una vez que éste es declarado. Sin embargo no todo es tan bueno, pues si no lo hacemos al momento de declarar el atributo, entonces estaremos obligados a hacerlo en el constructor de la clase. Java debe asegurarse que el valor de una variable final sea asignado y las dos únicas posibilidades son el constructor o en la declaración misma del atributo. Existe algo particular con este comportamiento de Java y es que necesitamos que todos los constructores le den valor al atributo constante (si no lo hicimos al momento de declararlo), de este modo, si tenemos más de un constructor es obligatorio que cada uno de ellos le asigne valor al atributo constante (final), pues no basta que uno de ellos lo haga, Java nos permitirá compilar el código siempre y cuando todos y cada uno de los constructores le de valor al atributo final (constante), pues si usáramos un constructor que no le diera valor a dicho atributo, éste quedaría con valor nulo y nunca podrá ser cambiado lo cual es inconsistente. Veamos en código de lo que estoy hablando:

Constructores y atributos constantes en Java

	
public class Constantes
{
	private int atributo; //Este atributo no es constante
	private final String atribConstante; //Constante y no ha sido inicializado
	
	//Primer constructor
	//Ver que en éste le asigna valor al atributo final
	Constantes(String valor)
	{
		//Aquí se inicializó el atributo
		atribConstante = valor;
	}
	
	//Segundo constructor
	//Éste no le asigna valor al atributo final
	Constantes(int valor)
	{
		//Aquí se inicializó el atributo
		atributo = valor;
		//Pero no se le dio valor al atributo final
		
		//atribConstante ="";
		
	}
	
	//Lo anterior es un error!!
	//Se debe descomentar la linea 22 para solucionarlo
}
	

Métodos y clases final

El modificador final también puede ser usado en las clases y en los métodos, de manera similar a como se hace con los datos y los atributos, sin embargo el significado que esto posee es diferente.

Final class. Clases final

Una clase final es una clase que no puede ser extendida, es decir ninguna otra clase puede ser hija de ésta, será entonces una clase única y que no tendrá herencia o herederos al no poder ser extendida. Veamos:

Declaramos una clase "Madre" que será final, esto quiere decir que no podrá ser extendida por otra

	
//Se declara la clase como final
public final class ClaseMadre
{
	//Atributos de la clase
	private int atributo1;
	private String atributo2;
	
	//Método de la clase
	public void metodo1()
	{
		System.out.print("Hola");
	}	
}
	

Declaramos una clase "Hija" que intentará extender de la clase "Madre", la cual es final. Esto generará un error de compilación y no podremos ejecutar nuestro código.

	
//Se declara la clase como hija de madre
//Esto genera un error
public class ClaseHija extends ClaseMadre
{
	//Atributos de la clase
	private int atributo1;
	private String atributo2;
	
	//Método de la clase
	public void metodo1()
	{
		System.out.print("Hola");
	}	
}
	

Métodos final

Un método final no puede ser redefinido por una clase hija. Esto quiere decir que si yo defino un método final en la clase X y luego la clase Y es hija de la clase X, entonces la clase Y no podrá cambiar la definición de dicho método, puesto que éste es final. Veamos:

Declaramos una clase "Madre" que será tendrá un método final, esto quiere decir que dicho método no podrá ser redefinido.

	
//Se declara la clase como final
public class ClaseMadre
{
	//Atributos de la clase
	private int atributo1;
	private String atributo2;
	
	//Método final de la clase
	public final void metodo1()
	{
		System.out.print("Hola");
	}	
}
	

Declaramos una clase "Hija" que extenderá de la clase "Madre" sin problemas e intentará redefinir el método1. Esto generará un error de compilación y no podremos ejecutar nuestro código.

	
//Se declara la clase como hija de madre
public class ClaseHija extends ClaseMadre
{
	//Atributos de la clase
	private int atributo1;
	private String atributo2;
	
	//Método de la clase
	public void metodo1()
	{
		System.out.print("Adios");
	}
	//Lo anterior genera error, pues no se puede redefinir un método final
	
	public int metodo1(int valor)
	{
		return valor;
	}
	//Esto NO es un error, pues NO estamos redefiniendo el método
	//Redefinir no es lo mismo que sobrecargar.
}
	

En el ejemplo anterior acabamos de ver como hemos intentado redefinir el método de la clase madre y esto no generaría un error, pues método1 es final. Quiero hacer la aclaración aquí. Redefinir no es lo mismo que sobrecargar. Cuando sobrecargamos un método estamos cambiando la firma del método y esto lo podemos hacer independientemente de si el método es final o no. Sin embargo redefinir el método es intentar hacer que la clase Hija tenga el mismo método (sin sobrecargarlo), pero que haga algo diferente, esto es lo que no podremos hacer. En este caso intentamos que el método mostrara en pantalla "Adios" pero no podemos hacerlo, mientras que luego SOBRECARGAMOS el método1, poniéndole un parámetro de entrada y un valor de retorno.

Sé que esto último es bastante confuso y avanzado, sin embargo quise tocar el tema para ir abriéndome a otras cosas y mostrando el alto potencial que tiene Java. En otras secciones hablaré con detalle acerca de herencia en Java, todo esto de clases Hijas, clases Madre y varias cosas más. Recuerda que cualquier duda o problema lo puedes poner en la sección de comentarios.

Pues bien, hecha esta última aclaración doy por finalizada esta sección. Espero que todo haya quedado lo suficientemente claro o por lo menos la parte de datos y atributos constantes. No te preocupes si no comprender bien la parte de clases y métodos final, pues más adelante hablaré de ellos con más detalle. No olvides dejar tus dudas, comentarios y/o sugerencias, en la sección de comentarios. Nos leemos.

La última actualización de este artículo fue hace 1 año