Java
Tutorial Java: Variables
Java variables: declaración y ejemplos. Aprende a declarar y usar variables en Java con ejemplos prácticos y detallados.
Aprende Java y certifícateDeclaración de variables
En Java, las variables son espacios de memoria que se utilizan para almacenar datos durante la ejecución de un programa. Antes de poder utilizar una variable, es necesario declararla, lo que implica especificar su tipo de dato y asignarle un nombre identificador.
La sintaxis básica para declarar una variable en Java es:
tipo nombreVariable;
Donde tipo
representa el tipo de dato que almacenará la variable y nombreVariable
es el identificador que se utilizará para referenciarla en el código.
Tipos de datos para variables
En Java se pueden declarar variables de diferentes tipos de datos, que se clasifican principalmente en dos categorías:
- Tipos primitivos: Almacenan valores simples y están predefinidos en el lenguaje
- Tipos de referencia: Almacenan referencias a objetos
Para los tipos primitivos, se puede declarar variables de la siguiente manera:
int edad; // Declara una variable entera
double salario; // Declara una variable de punto flotante
boolean activo; // Declara una variable booleana
char inicial; // Declara una variable de carácter
byte pequeño; // Declara una variable byte
short corto; // Declara una variable short
long grande; // Declara una variable long
float decimal; // Declara una variable float
Para los tipos de referencia, la declaración sigue el mismo patrón:
String nombre; // Declara una variable para cadenas de texto
Integer numero; // Declara una variable de la clase envoltorio Integer
ArrayList<String> lista; // Declara una variable para una lista de cadenas
Declaración múltiple de variables
Se pueden declarar varias variables del mismo tipo en una sola línea, separándolas por comas:
int x, y, z; // Declara tres variables enteras
String nombre, apellido; // Declara dos variables de tipo String
Declaración con inferencia de tipos
Desde Java 10, se puede utilizar la palabra clave var
para que el compilador infiera el tipo de la variable a partir del valor asignado. Sin embargo, esto solo funciona con variables locales y requiere inicialización inmediata:
var contador = 0; // El compilador infiere que contador es de tipo int
var mensaje = "Hola"; // El compilador infiere que mensaje es de tipo String
var lista = new ArrayList<String>(); // Infiere ArrayList<String>
Es importante destacar que el uso de var
no convierte a Java en un lenguaje de tipado dinámico. El tipo se sigue determinando en tiempo de compilación y no puede cambiar durante la ejecución.
Ámbito de las variables declaradas
El ámbito o scope de una variable determina dónde es accesible dentro del código. En Java, las variables pueden tener diferentes ámbitos:
public class EjemploAmbito {
int variableInstancia; // Variable de instancia, accesible en toda la clase
public void metodo() {
int variableLocal; // Variable local, solo accesible dentro de este método
if (true) {
int variableBloque; // Variable de bloque, solo accesible dentro del if
}
// variableBloque no es accesible aquí
}
// variableLocal no es accesible aquí
}
Consideraciones importantes
Al declarar variables en Java, se deben tener en cuenta algunas consideraciones:
- Las variables deben declararse antes de usarse.
- El nombre de la variable debe ser un identificador válido en Java.
- Se recomienda que el nombre sea descriptivo y siga las convenciones de nomenclatura.
- Las variables locales no se inicializan automáticamente, a diferencia de las variables de instancia.
public class EjemploInicializacion {
int variableInstancia; // Se inicializa automáticamente a 0
public void metodo() {
int variableLocal; // No se inicializa automáticamente
// System.out.println(variableLocal); // Error: variable no inicializada
variableLocal = 10; // Ahora sí se puede usar
System.out.println(variableLocal);
}
}
Declaración de variables en bucles y estructuras de control
Es común declarar variables dentro de estructuras de control como bucles for
o bloques try-catch
:
// Declaración en bucle for
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
// La variable i no es accesible fuera del bucle
// Declaración en try-with-resources (desde Java 7)
try (var archivo = new FileInputStream("datos.txt")) {
// Código que usa el archivo
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
// La variable archivo se cierra automáticamente y no es accesible aquí
Inicialización de variables
La inicialización de variables es el proceso mediante el cual se asigna un valor inicial a una variable después de su declaración. En Java, esta operación es fundamental para garantizar que las variables contengan valores válidos antes de ser utilizadas en operaciones o expresiones.
Sintaxis básica de inicialización
Existen dos formas principales de inicializar variables en Java:
// Declaración e inicialización separadas
tipo nombreVariable;
nombreVariable = valor;
// Declaración e inicialización en una sola línea
tipo nombreVariable = valor;
La segunda forma es más concisa y se utiliza con mayor frecuencia en el código Java moderno.
Inicialización de tipos primitivos
Los tipos primitivos se pueden inicializar con valores literales que correspondan a su tipo:
int contador = 0;
double precio = 29.99;
char letra = 'A';
boolean activo = true;
byte pequeño = 127;
short medio = 32000;
long grande = 9223372036854775807L; // La 'L' indica literal de tipo long
float decimal = 3.14f; // La 'f' indica literal de tipo float
Es importante notar que para los literales long
se debe añadir el sufijo L
y para los float
el sufijo f
para distinguirlos de los tipos int
y double
respectivamente.
Inicialización de tipos de referencia
Los tipos de referencia generalmente se inicializan mediante el operador new
que crea una nueva instancia del objeto:
String mensaje = "Hola mundo"; // Inicialización especial para String
String otraMensaje = new String("Hola"); // Forma alternativa menos común
ArrayList<Integer> numeros = new ArrayList<>(); // Inicialización con diamante vacío
Date fechaActual = new Date(); // Crea objeto con la fecha actual
Para String
, Java proporciona una sintaxis especial que permite inicializar directamente con literales de cadena entre comillas dobles, sin necesidad de usar new
.
Inicialización con valores por defecto
Las variables de instancia (campos de clase) y las variables estáticas se inicializan automáticamente con valores por defecto si no se especifica un valor inicial:
public class EjemploValoresPorDefecto {
int numero; // Se inicializa a 0
double decimal; // Se inicializa a 0.0
boolean condicion; // Se inicializa a false
char caracter; // Se inicializa a '\u0000' (carácter nulo)
String texto; // Se inicializa a null
Object objeto; // Se inicializa a null
public void mostrarValores() {
System.out.println("Número: " + numero);
System.out.println("Decimal: " + decimal);
System.out.println("Condición: " + condicion);
System.out.println("Carácter: " + (int)caracter); // Muestra el valor ASCII
System.out.println("Texto: " + texto);
System.out.println("Objeto: " + objeto);
}
}
Sin embargo, las variables locales (declaradas dentro de métodos) deben inicializarse explícitamente antes de usarse, ya que no reciben valores por defecto:
public void metodoEjemplo() {
int contador;
// System.out.println(contador); // Error de compilación: variable no inicializada
contador = 10; // Inicialización explícita
System.out.println(contador); // Ahora funciona correctamente
}
Inicialización en bloque
Para inicializaciones más complejas, se pueden utilizar bloques de inicialización:
public class EjemploInicializacionBloque {
private final List<String> elementos;
{
// Bloque de inicialización de instancia
elementos = new ArrayList<>();
elementos.add("Elemento 1");
elementos.add("Elemento 2");
elementos.add("Elemento 3");
}
// Constructor que aprovecha la inicialización en bloque
public EjemploInicializacionBloque() {
System.out.println("Constructor llamado con elementos ya inicializados");
}
}
También existen bloques de inicialización estáticos para variables de clase:
public class ConfiguracionApp {
private static final Map<String, String> CONFIG;
static {
// Bloque de inicialización estática
CONFIG = new HashMap<>();
CONFIG.put("timeout", "30");
CONFIG.put("maxConnections", "100");
CONFIG.put("debugMode", "false");
// Se podría cargar desde un archivo o base de datos
try {
// Código de carga de configuración
System.out.println("Configuración cargada");
} catch (Exception e) {
System.err.println("Error al cargar configuración");
}
}
}
Inicialización con expresiones
Las variables pueden inicializarse con expresiones que se evalúan en tiempo de ejecución:
int a = 5;
int b = 10;
int suma = a + b; // Inicialización con una expresión aritmética
int max = (a > b) ? a : b; // Inicialización con operador ternario
String nombre = obtenerNombre(); // Inicialización con el resultado de un método
double aleatorio = Math.random(); // Inicialización con método de la biblioteca estándar
Inicialización de arrays
Los arrays en Java tienen una sintaxis especial para su inicialización:
// Declaración e inicialización en una línea
int[] numeros = {1, 2, 3, 4, 5};
// Declaración e inicialización separadas
String[] nombres;
nombres = new String[] {"Ana", "Juan", "Carlos"};
// Inicialización con tamaño específico (elementos con valores por defecto)
double[] precios = new double[5]; // Crea array de 5 elementos inicializados a 0.0
// Inicialización con bucle
char[] letras = new char[26];
for (int i = 0; i < letras.length; i++) {
letras[i] = (char)('A' + i);
}
Inicialización con inferencia de tipos
Con la inferencia de tipos mediante var
, la inicialización es obligatoria:
var contador = 0; // Infiere tipo int
var mensaje = "Hola"; // Infiere tipo String
var numeros = new int[] {1, 2, 3}; // Infiere array de int
var lista = new ArrayList<String>(); // Infiere ArrayList<String>
// No es válido:
// var numero; // Error: no se puede inferir el tipo sin inicialización
Inicialización perezosa (lazy initialization)
En algunos casos, se prefiere retrasar la inicialización hasta que realmente se necesite el valor, especialmente para recursos costosos:
public class ServicioCostoso {
private ExpensiveResource recurso;
public ExpensiveResource getRecurso() {
if (recurso == null) {
recurso = new ExpensiveResource(); // Inicialización perezosa
}
return recurso;
}
}
Este patrón es común en aplicaciones donde se busca optimizar el rendimiento, aunque en entornos multihilo puede requerir sincronización adicional.
Buenas prácticas de inicialización
- Inicializar variables lo más cerca posible de su primer uso.
- Preferir la inicialización en la misma línea de la declaración cuando sea posible.
- Utilizar valores significativos para la inicialización, evitando valores "mágicos".
- Para constantes, utilizar nombres en mayúsculas y valores claros.
- Considerar la inmutabilidad cuando sea apropiado, usando
final
para variables que no cambiarán.
// Ejemplo de buenas prácticas
final int MAX_INTENTOS = 3;
final String PREFIJO_CODIGO = "USR";
int contador = 0;
String nombreUsuario = obtenerNombreDeBaseDeDatos();
Reglas y convenciones en Java para nombrar variables
En Java, el nombrado de variables sigue un conjunto de reglas sintácticas obligatorias y convenciones de estilo recomendadas.
Reglas sintácticas obligatorias
Las reglas que deben cumplirse para que el código compile correctamente son:
- Los nombres de variables pueden contener letras, dígitos, el símbolo de dólar (
$
) y el guion bajo (_
). - Deben comenzar con una letra, el símbolo de dólar o el guion bajo, nunca con un dígito.
- No pueden ser palabras reservadas de Java (como
if
,class
,while
, etc.). - Java distingue entre mayúsculas y minúsculas (case-sensitive), por lo que
contador
yContador
serían variables diferentes. - No hay límite práctico para la longitud del nombre, aunque se recomienda que sean concisos.
// Nombres válidos de variables
int edad;
double $precio;
String _nombre;
boolean esActivo;
long número123; // Los caracteres Unicode son válidos, pero no recomendados
// Nombres no válidos (errores de compilación)
int 1numero; // No puede comenzar con un dígito
float if; // No puede ser una palabra reservada
char class; // No puede ser una palabra reservada
Convenciones de estilo recomendadas
Aunque no son obligatorias para la compilación, estas convenciones son ampliamente seguidas en la comunidad Java:
Notación camelCase
Para variables y métodos, se utiliza la notación camelCase: la primera palabra en minúsculas y cada palabra adicional comienza con mayúscula:
int edadUsuario;
String nombreCompleto;
boolean estaActivo;
double tasaInteresAnual;
Nombres descriptivos y significativos
Los nombres deben ser autoexplicativos, indicando claramente el propósito de la variable:
// Preferir esto:
int edadEmpleado;
double precioTotal;
boolean estaCompletado;
// Evitar esto:
int e;
double x;
boolean flag;
Abreviaturas y acrónimos
Las abreviaturas y acrónimos generalmente se tratan como palabras normales en camelCase, excepto cuando aparecen al inicio:
String url; // No URL (cuando está al inicio)
String nombreHtml; // No nombreHTML
HttpServletRequest request; // Excepción común para tipos bien conocidos
int identificadorId; // Redundante, mejor usar solo "identificador"
Prefijos y sufijos
Se evita el uso de notación húngara (prefijos que indican el tipo) y otros prefijos como:
// Evitar esto:
int iEdad; // Prefijo de tipo
String strNombre; // Prefijo de tipo
boolean bActivo; // Prefijo de tipo
// Preferir esto:
int edad;
String nombre;
boolean activo;
Variables de un solo uso o temporales
Para variables de ámbito muy limitado o índices de bucles, se aceptan nombres cortos:
for (int i = 0; i < 10; i++) {
// 'i' es aceptable como índice de bucle
}
int x = punto.getX(); // 'x' es claro en este contexto
Constantes
Las constantes (variables static final
) se escriben en mayúsculas con palabras separadas por guiones bajos:
public static final int MAX_USUARIOS = 100;
public static final String PREFIJO_CODIGO = "USR";
public static final double PI = 3.14159265359;
Variables booleanas
Para variables booleanas, se recomienda usar prefijos como es
, tiene
, puede
o similares:
boolean esValido;
boolean tienePermisos;
boolean puedeEditar;
boolean debeActualizar;
Casos especiales
Variables de instancia (campos)
Aunque siguen las mismas convenciones que las variables locales, a veces se les añade un guion bajo al final para distinguirlas de parámetros con el mismo nombre:
public class Usuario {
private String nombre_; // Campo de instancia
public void setNombre(String nombre) {
this.nombre_ = nombre; // Distingue el parámetro del campo
}
}
Sin embargo, la práctica más común es usar this
para referirse a los campos:
public class Usuario {
private String nombre; // Campo de instancia
public void setNombre(String nombre) {
this.nombre = nombre; // Uso de 'this' para distinguir
}
}
Parámetros de métodos
Siguen las mismas convenciones que las variables locales:
public void procesarPago(double monto, String moneda, boolean esUrgente) {
// Implementación
}
Prácticas a evitar
- Nombres de una sola letra (excepto para índices de bucles o coordenadas).
- Nombres muy similares que pueden causar confusión.
- Nombres engañosos que no reflejan el propósito real de la variable.
- Nombres excesivamente largos que dificultan la lectura.
// Evitar esto:
int a; // Poco descriptivo
int longitudDeNombreDeVariable; // Excesivamente largo
int longitud1, longitud2; // Nombres muy similares
int size; // Engañoso si no es realmente un tamaño
Herramientas de verificación
Existen herramientas como Checkstyle, PMD y SonarQube que pueden configurarse para verificar automáticamente que el código siga estas convenciones:
<!-- Ejemplo de configuración de Checkstyle para verificar nombres de variables -->
<module name="LocalVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
Variables locales y de instancia
En Java, las variables se clasifican en diferentes categorías según su ámbito y ciclo de vida. Dos de las categorías más importantes son las variables locales y las variables de instancia, cada una con características y usos específicos.
Variables locales
Las variables locales son aquellas que se declaran dentro de un método, constructor o bloque de código. Sus características principales son:
- Se crean cuando se ejecuta el bloque donde están declaradas.
- Se destruyen cuando finaliza la ejecución del bloque.
- No son accesibles desde fuera del bloque donde se declaran.
- No tienen un valor por defecto, deben inicializarse explícitamente antes de usarse.
- No pueden tener modificadores de acceso (
public
,private
, etc.). - Pueden declararse con el modificador
final
para crear constantes locales.
public void calcularTotal() {
int cantidad = 5; // Variable local
double precioUnitario = 19.99; // Variable local
final double TASA_IMPUESTO = 0.21; // Constante local (final)
double subtotal = cantidad * precioUnitario;
double impuesto = subtotal * TASA_IMPUESTO;
double total = subtotal + impuesto;
System.out.println("Total: " + total);
} // Aquí todas las variables locales dejan de existir
Las variables locales también incluyen los parámetros de método, que son variables especiales inicializadas con los valores pasados al método cuando se invoca:
public double calcularArea(double longitud, double anchura) {
// longitud y anchura son variables locales (parámetros)
return longitud * anchura;
}
Variables de instancia
Las variables de instancia, también llamadas campos o atributos, se declaran dentro de una clase pero fuera de cualquier método. Sus características principales son:
- Se crean cuando se instancia un objeto de la clase.
- Se destruyen cuando el objeto es eliminado por el recolector de basura.
- Cada objeto tiene su propia copia de las variables de instancia.
- Tienen valores por defecto si no se inicializan explícitamente.
- Pueden tener modificadores de acceso (
public
,private
,protected
). - Pueden declararse como
final
para crear constantes de instancia. - Pueden declararse como
static
para convertirlas en variables de clase.
public class Producto {
// Variables de instancia
private String nombre; // Por defecto: null
private double precio; // Por defecto: 0.0
private int stock; // Por defecto: 0
private final String codigo; // Constante de instancia, debe inicializarse
public Producto(String nombre, double precio, String codigo) {
this.nombre = nombre;
this.precio = precio;
this.codigo = codigo; // Inicialización de constante de instancia
}
public void mostrarInfo() {
System.out.println("Producto: " + nombre);
System.out.println("Precio: " + precio);
System.out.println("Stock: " + stock);
System.out.println("Código: " + codigo);
}
}
Diferencias clave entre variables locales y de instancia
Característica | Variables locales | Variables de instancia |
---|---|---|
Ámbito | Limitado al bloque donde se declaran | Accesibles en toda la clase |
Ciclo de vida | Temporal (durante la ejecución del bloque) | Ligado al objeto (hasta que se destruye) |
Inicialización | Obligatoria antes de usar | Automática con valores por defecto |
Modificadores de acceso | No permitidos | Permitidos (public , private , etc.) |
Valor por defecto | No tienen | Sí tienen (0 , false , null , etc.) |
Visibilidad | Solo en el bloque donde se declaran | Según el modificador de acceso |
Sombreado de variables (Variable Shadowing)
Cuando una variable local tiene el mismo nombre que una variable de instancia, la variable local "sombrea" o "oculta" a la variable de instancia en ese ámbito:
public class Empleado {
private String nombre; // Variable de instancia
public void setNombre(String nombre) { // Parámetro con el mismo nombre
// Aquí, 'nombre' se refiere al parámetro, no a la variable de instancia
this.nombre = nombre; // 'this' se usa para acceder a la variable de instancia
}
public void ejemploSombreado() {
int edad = 30; // Variable local
if (edad > 18) {
String nombre = "Anónimo"; // Variable local que sombrea a la de instancia
System.out.println(nombre); // Imprime "Anónimo"
}
System.out.println(this.nombre); // Accede a la variable de instancia
}
}
El sombreado puede causar confusión y errores, por lo que se recomienda evitarlo cuando sea posible, excepto en los casos comunes como los parámetros de constructores y métodos setter.
Variables estáticas (de clase)
Además de las variables locales y de instancia, existe un tercer tipo importante: las variables estáticas o variables de clase. Se declaran con el modificador static
:
public class Contador {
private static int total = 0; // Variable estática (de clase)
private int valor; // Variable de instancia
public Contador() {
valor = 0;
total++; // Incrementa el contador de instancias
}
public static int getTotal() {
return total; // Acceso a variable estática
}
}
Las variables estáticas pertenecen a la clase en lugar de a instancias individuales, por lo que:
- Solo existe una copia de cada variable estática, compartida por todas las instancias.
- Se pueden acceder incluso sin crear instancias de la clase.
- Se inicializan cuando la clase se carga en memoria.
- Suelen utilizarse para constantes, contadores globales o recursos compartidos.
Buenas prácticas
- Minimizar el ámbito: Declarar variables en el ámbito más pequeño posible.
- Encapsulación: Hacer las variables de instancia
private
y proporcionar métodos de acceso. - Inicialización temprana: Inicializar variables lo más cerca posible de su declaración.
- Evitar variables globales: Preferir parámetros y valores de retorno para comunicar datos.
- Usar nombres descriptivos: Especialmente importante para variables con ámbitos amplios.
public class EjemploBuenasPracticas {
// Variables de instancia encapsuladas
private String nombre;
private int edad;
// Constructor que inicializa todas las variables
public EjemploBuenasPracticas(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
public void procesarDatos() {
// Variable local con ámbito limitado
boolean datosValidos = validar();
if (datosValidos) {
// Variables locales solo usadas en este bloque
String mensajeExito = "Procesamiento completado para: " + nombre;
System.out.println(mensajeExito);
}
}
private boolean validar() {
return edad >= 18;
}
}
Variables finales constantes
En Java, las variables finales o constantes son aquellas cuyo valor no puede cambiar una vez asignado y se declaran utilizando el modificador final
.
Declaración de variables finales
La sintaxis básica para declarar una variable final es:
final tipo NOMBRE_VARIABLE = valor;
Por convención, las constantes se nombran en mayúsculas con palabras separadas por guiones bajos, aunque esto es obligatorio solo para constantes estáticas.
Tipos de variables finales
Dependiendo de su ámbito, las variables finales pueden ser:
Constantes locales
Se declaran dentro de métodos o bloques:
public void calcularImpuesto(double precio) {
final double TASA_IVA = 0.21;
double impuesto = precio * TASA_IVA;
System.out.println("Impuesto: " + impuesto);
}
Estas constantes son útiles cuando se necesita un valor que no cambiará dentro del método, pero que no tiene sentido definir a nivel de clase.
Constantes de instancia
Son variables de instancia declaradas como final
:
public class Persona {
private final String dni;
private String nombre;
private int edad;
public Persona(String dni, String nombre, int edad) {
this.dni = dni; // Debe inicializarse en el constructor
this.nombre = nombre;
this.edad = edad;
}
// No puede existir un método que modifique dni
// public void setDni(String dni) { this.dni = dni; } // Error de compilación
}
Las constantes de instancia deben inicializarse:
- En la declaración
- En un bloque de inicialización de instancia
- En todos los constructores
Una vez inicializadas, no pueden modificarse durante toda la vida del objeto.
Constantes estáticas (de clase)
Son las constantes más comunes en Java, declaradas como static final
:
public class Configuracion {
public static final int MAX_CONEXIONES = 100;
public static final String VERSION = "1.0.3";
public static final double PI = 3.14159265359;
// Para constantes complejas, se puede usar un bloque estático
public static final List<String> PAISES_SOPORTADOS;
static {
List<String> paises = new ArrayList<>();
paises.add("España");
paises.add("Francia");
paises.add("Portugal");
paises.add("Italia");
PAISES_SOPORTADOS = Collections.unmodifiableList(paises);
}
}
Estas constantes:
- Se inicializan cuando la clase se carga en memoria
- Son compartidas por todas las instancias de la clase
- Se acceden directamente a través del nombre de la clase
- Son ideales para valores que son verdaderamente constantes en toda la aplicación
Parámetros finales
Los parámetros de métodos también pueden declararse como final
:
public void procesarDatos(final String datos, final int maxIntentos) {
// datos = "Nuevos datos"; // Error de compilación
// maxIntentos = 5; // Error de compilación
// Uso normal de los parámetros
System.out.println("Procesando: " + datos);
}
Esto garantiza que los parámetros no se modificarán dentro del método, lo que puede ser útil para:
- Evitar errores accidentales
- Mejorar la legibilidad del código
- Facilitar la programación concurrente
Referencias finales vs. objetos inmutables
Es importante entender que final
solo hace que la referencia sea constante, no el objeto al que apunta:
final List<String> nombres = new ArrayList<>();
// nombres = new ArrayList<>(); // Error: no se puede reasignar la referencia
// Pero sí se puede modificar el contenido del objeto
nombres.add("Ana"); // Esto es válido
nombres.add("Juan"); // Esto también es válido
Para crear objetos verdaderamente inmutables, se deben tomar medidas adicionales:
// Creación de una lista inmutable
final List<String> COLORES = List.of("Rojo", "Verde", "Azul");
// COLORES.add("Amarillo"); // Lanza UnsupportedOperationException en tiempo de ejecución
// Alternativa con Collections
final List<String> DIAS = Collections.unmodifiableList(
Arrays.asList("Lunes", "Martes", "Miércoles", "Jueves", "Viernes")
);
Ventajas de usar variables finales
- Seguridad: Previene modificaciones accidentales de valores que deberían ser constantes.
- Claridad: Comunica la intención de que el valor no debe cambiar.
- Optimización: Permite al compilador realizar ciertas optimizaciones.
- Concurrencia: Facilita la programación concurrente segura.
- Diseño: Fomenta la inmutabilidad, un principio de diseño valioso.
Constantes en interfaces
Las interfaces pueden contener constantes, que son implícitamente public static final
:
public interface ConfiguracionSistema {
int TIMEOUT_CONEXION = 30000; // Implícitamente public static final
String SERVIDOR_PRINCIPAL = "srv01.ejemplo.com";
double VERSION_API = 2.1;
}
Estas constantes se pueden acceder directamente a través del nombre de la interfaz:
int timeout = ConfiguracionSistema.TIMEOUT_CONEXION;
Sin embargo, este uso ha sido parcialmente reemplazado por clases de utilidad o enumeraciones en el código Java moderno.
Enumeraciones como alternativa a constantes
Para conjuntos de constantes relacionadas, las enumeraciones (enum
) ofrecen una alternativa más robusta:
// En lugar de:
public class EstadoPedido {
public static final int PENDIENTE = 0;
public static final int PROCESANDO = 1;
public static final int ENVIADO = 2;
public static final int ENTREGADO = 3;
}
// Mejor usar:
public enum EstadoPedido {
PENDIENTE, PROCESANDO, ENVIADO, ENTREGADO
}
Las enumeraciones proporcionan:
- Seguridad de tipo (type-safety)
- Métodos y campos adicionales
- Integración con
switch
- Prevención de valores inválidos
public enum DiaSemana {
LUNES(true), MARTES(true), MIERCOLES(true), JUEVES(true),
VIERNES(true), SABADO(false), DOMINGO(false);
private final boolean diaLaboral;
DiaSemana(boolean diaLaboral) {
this.diaLaboral = diaLaboral;
}
public boolean esDiaLaboral() {
return diaLaboral;
}
}
Buenas prácticas con variables finales
- Usar
final
liberalmente: Declarar comofinal
cualquier variable que no necesite cambiar. - Preferir constantes a literales: Evitar "números mágicos" o cadenas literales en el código.
- Agrupar constantes relacionadas: Usar clases de utilidad o enumeraciones para organizar constantes.
- Nombrar claramente: Usar nombres descriptivos en mayúsculas para constantes estáticas.
- Considerar la inmutabilidad: Para referencias a objetos, considerar hacer inmutable el objeto referenciado.
public class ConfiguracionApp {
// Agrupación de constantes relacionadas
public static final class Tiempos {
public static final int TIMEOUT_CONEXION = 30000;
public static final int INTERVALO_REINTENTO = 5000;
public static final int MAX_TIEMPO_ESPERA = 120000;
private Tiempos() {} // Constructor privado para evitar instanciación
}
public static final class Rutas {
public static final String DIRECTORIO_DATOS = "/var/data/";
public static final String ARCHIVO_CONFIG = "config.json";
private Rutas() {}
}
}
// Uso:
int timeout = ConfiguracionApp.Tiempos.TIMEOUT_CONEXION;
Ejercicios de esta lección Variables
Evalúa tus conocimientos de esta lección Variables con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Clases abstractas
Streams: reduce()
Streams: flatMap()
Llamada y sobrecarga de funciones
Métodos referenciados
Métodos de la clase String
Representación de Fecha
Operadores lógicos
Tipos de datos
Estructuras de iteración
Streams: forEach()
Objetos
Funciones lambda
Uso de Scanner
CRUD en Java de modelo Customer sobre un ArrayList
Tipos de variables
Streams: collect()
Operadores aritméticos
Interfaz funcional Consumer
API java.nio 2
API Optional
Interfaz funcional Function
Encapsulación
Interfaces
Uso de API Optional
Representación de Hora
Herencia básica
Clases y objetos
Interfaz funcional Supplier
HashMap
Sobrecarga de métodos
Polimorfismo de tiempo de ejecución
OOP en Java
Creación de Streams
Streams: min max
Métodos avanzados de la clase String
Polimorfismo de tiempo de compilación
Excepciones
Herencia avanzada
Estructuras de selección
Uso de interfaces
HashSet
Objeto Scanner
Streams: filter()
Operaciones de Streams
Interfaz funcional Predicate
Streams: sorted()
Configuración de entorno
CRUD en Java de modelo Customer sobre un HashMap
Uso de variables
Clases
Streams: distinct()
Streams: count()
ArrayList
Datos de referencia
Interfaces funcionales
Métodos básicos de la clase String
Instalación
Funciones
Estructuras de control
Herencia de clases
Streams: map()
Funciones y encapsulamiento
Streams: match
Gestión de errores y excepciones
Datos primitivos
Todas las lecciones de Java
Accede a todas las lecciones de Java y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De Java
Introducción Y Entorno
Configuración De Entorno Java
Introducción Y Entorno
Ecosistema Jakarta Ee De Java
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Excepciones
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Sobrecarga De Métodos
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
La Clase Scanner
Programación Orientada A Objetos
Métodos De La Clase String
Programación Orientada A Objetos
Listas
Framework Collections
Conjuntos
Framework Collections
Mapas
Framework Collections
Funciones Lambda
Programación Funcional
Interfaz Funcional Consumer
Programación Funcional
Interfaz Funcional Predicate
Programación Funcional
Interfaz Funcional Supplier
Programación Funcional
Interfaz Funcional Function
Programación Funcional
Métodos Referenciados
Programación Funcional
Creación De Streams
Programación Funcional
Operaciones Intermedias Con Streams: Map()
Programación Funcional
Operaciones Intermedias Con Streams: Filter()
Programación Funcional
Operaciones Intermedias Con Streams: Distinct()
Programación Funcional
Operaciones Finales Con Streams: Collect()
Programación Funcional
Operaciones Finales Con Streams: Min Max
Programación Funcional
Operaciones Intermedias Con Streams: Flatmap()
Programación Funcional
Operaciones Intermedias Con Streams: Sorted()
Programación Funcional
Operaciones Finales Con Streams: Reduce()
Programación Funcional
Operaciones Finales Con Streams: Foreach()
Programación Funcional
Operaciones Finales Con Streams: Count()
Programación Funcional
Operaciones Finales Con Streams: Match
Programación Funcional
Api Optional
Programación Funcional
Api Java.nio 2
Entrada Y Salida (Io)
Api Java.time
Api Java.time
Certificados de superación de Java
Supera todos los ejercicios de programación del curso de Java y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Identificar y declarar tipos de variables en Java
- Diferenciar entre variables locales, de instancia y estáticas
- Aplicar la inferencia de tipos en Java desde la versión 10
- Entender el ámbito y la visibilidad de las variables
- Aplicar buenas prácticas en la declaración de variables