Skip to content

2. Tipos de Datos y Variables

En Java, los tipos de datos y las variables son conceptos fundamentales que definen cómo se almacena y manipula la información en un programa. Java es un lenguaje fuertemente tipado, lo que significa que todas las variables deben declararse con un tipo de dato específico antes de ser utilizadas.

Java clasifica los tipos de datos en dos categorías principales:

  1. Tipos primitivos: Almacenan valores simples y están predefinidos en el lenguaje.
  2. Tipos de referencia: Almacenan referencias a objetos y pueden ser clases, interfaces o arrays.

Java proporciona ocho tipos de datos primitivos, que se dividen en cuatro grupos:

Los tipos enteros almacenan números enteros (sin parte decimal) de diferentes tamaños:

  • Tamaño: 8 bits (1 byte)
  • Rango: -128 a 127
  • Valor por defecto: 0
  • Uso: Ahorro de memoria en arrays grandes o cuando se sabe que el valor estará dentro de su rango.
  • Ejemplo:
    byte edad = 25;

Los tipos de punto flotante almacenan números con parte decimal:

  • Tamaño: 32 bits (4 bytes)
  • Rango: Aproximadamente ±3.40282347E+38F (6-7 dígitos significativos)
  • Valor por defecto: 0.0f
  • Uso: Cuando se necesita precisión decimal con menor uso de memoria.
  • Ejemplo:
    float precio = 19.99f;
  • Nota: El sufijo ‘f’ indica que es un literal de tipo float.
  • Tamaño: 16 bits (2 bytes)
  • Rango: 0 a 65,535 (representa caracteres Unicode)
  • Valor por defecto: ‘\u0000’ (carácter nulo)
  • Uso: Almacena un único carácter Unicode.
  • Ejemplo:
    char letra = 'A';
// Ejemplos de caracteres especiales y Unicode
char nuevaLinea = '
';
char tabulacion = ' ';
char comillaSimple = ''';
char comillaDoble = '"';
char caracterUnicode = 'Ñ'; // Representa la letra Ñ (Ñ)
  • Tamaño: 1 bit (aunque la implementación JVM puede variar)
  • Valores posibles: true o false
  • Valor por defecto: false
  • Uso: Representa valores de verdad, utilizado en expresiones condicionales.
  • Ejemplo:
    boolean esActivo = true;
TipoTamañoRangoValor por defecto
byte8 bits-128 a 1270
short16 bits-32,768 a 32,7670
int32 bits-2,147,483,648 a 2,147,483,6470
long64 bits-9,223,372,036,854,775,808 a 9,223,372,036,854,775,8070L
float32 bits±3.40282347E+38F (6-7 dígitos)0.0f
double64 bits±1.79769313486231570E+308 (15 dígitos)0.0d
char16 bits0 a 65,535 (Unicode)‘\u0000’
boolean1 bit*true o falsefalse

Los tipos de datos de referencia son aquellos que almacenan referencias (direcciones de memoria) a objetos en lugar de almacenar los valores directamente. A diferencia de los tipos primitivos, los tipos de referencia se crean utilizando la palabra clave new (con algunas excepciones como String).

El tipo String es uno de los tipos de referencia más utilizados en Java. Representa una secuencia de caracteres y, aunque es técnicamente una clase, Java proporciona soporte especial para su uso:

  • Inmutabilidad: Los objetos String son inmutables, lo que significa que su contenido no puede cambiar después de ser creados.
  • Pool de Strings: Java mantiene un pool de strings para optimizar el uso de memoria.
  • Valor por defecto: null (como todos los tipos de referencia)
  • Ejemplo:
    String nombre = "María";

Los arrays son estructuras de datos que almacenan múltiples valores del mismo tipo:

  • Tamaño fijo: Una vez creado, el tamaño del array no puede cambiar.
  • Indexación: Los elementos se acceden mediante índices que comienzan en 0.
  • Valor por defecto: null para arrays de objetos, 0 para arrays numéricos, false para arrays de boolean.

Las clases son plantillas para crear objetos, que son instancias de esas clases:

// Definición de una clase
public class Persona {
// Atributos
private String nombre;
private int edad;
// Constructor
public Persona(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
// Métodos
public String getNombre() {
return nombre;
}
}
// Creación de objetos
Persona persona1 = new Persona("Ana", 30);
Persona persona2 = new Persona("Carlos", 25);

Java proporciona clases wrapper para cada tipo primitivo, permitiendo usarlos como objetos:

Tipo primitivoClase wrapper
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
// Autoboxing (conversión automática de primitivo a wrapper)
Integer num = 100; // Equivalente a: Integer num = Integer.valueOf(100);
// Unboxing (conversión automática de wrapper a primitivo)
int valor = num; // Equivalente a: int valor = num.intValue();
// Métodos útiles de las clases wrapper
String numStr = Integer.toString(42); // Convierte int a String
int numInt = Integer.parseInt("42"); // Convierte String a int
Integer max = Integer.MAX_VALUE; // Valor máximo de int

Las variables son espacios de memoria que almacenan valores que pueden cambiar durante la ejecución del programa. Las constantes, por otro lado, son valores que no pueden modificarse una vez definidos.

En Java, las variables deben declararse antes de usarse, especificando su tipo y nombre:

// Sintaxis básica
tipo nombreVariable;
// Ejemplos
int edad;
String nombre;
double salario;

Las variables pueden inicializarse en el momento de la declaración o posteriormente:

// Inicialización en la declaración
int edad = 25;
String nombre = "Juan";
// Inicialización posterior
double salario;
salario = 2500.50;

Java sigue ciertas convenciones para nombrar variables:

  • Los nombres deben comenzar con una letra, un signo de dólar ($) o un guión bajo (_).
  • Después del primer carácter, pueden contener letras, dígitos, signos de dólar y guiones bajos.
  • No se pueden usar palabras reservadas de Java como nombres de variables.
  • Java distingue entre mayúsculas y minúsculas (case-sensitive).

En Java, las constantes se declaran usando las palabras clave final y generalmente static (para constantes de clase):

// Constante local
final double PI = 3.14159;
// Constante de clase (estática)
public static final int DIAS_SEMANA = 7;
// Constantes en una interfaz (implícitamente public, static y final)
interface Constantes {
double GRAVEDAD = 9.8;
String EMPRESA = "Mi Empresa S.A.";
}

Variables de instancia vs. variables de clase

Section titled “Variables de instancia vs. variables de clase”

Pertenecen a un objeto específico (instancia de una clase).

public class Persona {
// Variables de instancia
private String nombre;
private int edad;
// Constructor
public Persona(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
}

La conversión de tipos en Java permite cambiar un valor de un tipo de dato a otro. Hay dos tipos principales de conversiones:

Ocurre automáticamente cuando se asigna un valor de un tipo de menor tamaño a uno de mayor tamaño, sin pérdida de información:

byte valorByte = 10;
short valorShort = valorByte; // Conversión implícita de byte a short
int valorInt = valorShort; // Conversión implícita de short a int
long valorLong = valorInt; // Conversión implícita de int a long
float valorFloat = valorLong; // Conversión implícita de long a float
double valorDouble = valorFloat; // Conversión implícita de float a double

Se requiere cuando se asigna un valor de un tipo de mayor tamaño a uno de menor tamaño, con posible pérdida de información. Se realiza mediante un operador de casting:

double valorDouble = 9.78;
float valorFloat = (float) valorDouble; // Conversión explícita de double a float
long valorLong = (long) valorFloat; // Conversión explícita de float a long
int valorInt = (int) valorLong; // Conversión explícita de long a int
short valorShort = (short) valorInt; // Conversión explícita de int a short
byte valorByte = (byte) valorShort; // Conversión explícita de short a byte
// Truncamiento de decimales
double precio = 23.56;
int precioRedondeado = (int) precio; // precioRedondeado = 23
// Posible pérdida de información
int numeroGrande = 130;
byte numeroPequeno = (byte) numeroGrande; // numeroPequeno = -126 (desbordamiento)

Java proporciona varios métodos para convertir entre diferentes tipos de datos. Estos métodos son especialmente útiles cuando se trabaja con tipos de referencia y primitivos:

Convierten un String a un tipo primitivo:

MétodoDescripciónEjemplo
Integer.parseInt(String s)
Convierte un String a int
int num = Integer.parseInt("42");
Double.parseDouble(String s)
Convierte un String a double
double d = Double.parseDouble("3.14");
Float.parseFloat(String s)
Convierte un String a float
float f = Float.parseFloat("2.5f");
Long.parseLong(String s)
Convierte un String a long
long l = Long.parseLong("9876543210");
Short.parseShort(String s)
Convierte un String a short
short s = Short.parseShort("128");
Byte.parseByte(String s)
Convierte un String a byte
byte b = Byte.parseByte("120");
Boolean.parseBoolean(String s)
Convierte un String a boolean
boolean bool = Boolean.parseBoolean("true");

El ámbito (scope) de una variable define dónde es accesible dentro del código. Java tiene varios niveles de ámbito:

Las variables declaradas dentro de un bloque de código (entre llaves {}) solo son accesibles dentro de ese bloque:

public void ejemploAmbitoBloque() {
// Inicio del bloque externo
int x = 10;
if (x > 5) {
// Inicio del bloque interno
int y = 20; // Variable de ámbito de bloque
System.out.println(x); // Accesible (x está en un bloque externo)
System.out.println(y); // Accesible
} // Fin del bloque interno
System.out.println(x); // Accesible
// System.out.println(y); // Error: y no es accesible aquí
} // Fin del bloque externo

Las variables declaradas dentro de un método (variables locales) solo son accesibles dentro de ese método:

public class EjemploAmbito {
public void metodo1() {
int a = 10; // Variable local al método1
System.out.println(a); // Accesible
}
public void metodo2() {
// System.out.println(a); // Error: a no es accesible aquí
int b = 20; // Variable local al método2
}
}

Las variables declaradas a nivel de clase (campos o atributos) son accesibles desde cualquier método dentro de la clase, dependiendo de su modificador de acceso:

public class Estudiante {
// Variables de instancia (nivel de clase)
private String nombre; // Accesible solo dentro de esta clase
protected int edad; // Accesible en esta clase y sus subclases
public String curso; // Accesible desde cualquier parte
public void establecerDatos(String nuevoNombre, int nuevaEdad) {
nombre = nuevoNombre; // Accesible
edad = nuevaEdad; // Accesible
System.out.println(curso); // Accesible
}
public void mostrarDatos() {
System.out.println(nombre); // Accesible
System.out.println(edad); // Accesible
}
}

Variables estáticas vs. variables de instancia

Section titled “Variables estáticas vs. variables de instancia”

Pertenecen a la clase, no a instancias específicas. Son compartidas por todas las instancias de la clase.

public class Contador {
// Variable estática (compartida por todas las instancias)
private static int contador = 0;
public Contador() {
contador++;
}
public static int getContador() {
return contador;
}
}

Uso:

Contador c1 = new Contador(); // contador = 1
Contador c2 = new Contador(); // contador = 2
System.out.println(Contador.getContador()); // Imprime 2

Sombreado de variables (Variable Shadowing)

Section titled “Sombreado de variables (Variable Shadowing)”

Ocurre cuando una variable declarada en un ámbito interno tiene el mismo nombre que una variable en un ámbito externo:

public class EjemploSombreado {
private int x = 10; // Variable de instancia
public void metodo() {
int x = 20; // Variable local que sombrea la variable de instancia
System.out.println(x); // Imprime 20 (variable local)
System.out.println(this.x); // Imprime 10 (variable de instancia)
}
public void otroMetodo(int x) { // Parámetro que sombrea la variable de instancia
System.out.println(x); // Imprime el valor del parámetro
System.out.println(this.x); // Imprime 10 (variable de instancia)
}
}
  • Java es un lenguaje fuertemente tipado con ocho tipos de datos primitivos: byte, short, int, long, float, double, char y boolean.
  • Las variables deben declararse con un tipo específico antes de usarse y pueden ser locales, de instancia o estáticas.
  • Las constantes se declaran con la palabra clave final y por convención se nombran en mayúsculas.
  • La conversión de tipos puede ser implícita (automática) cuando se convierte de un tipo menor a uno mayor, o explícita (mediante casting) cuando se convierte de un tipo mayor a uno menor.
  • El ámbito de una variable determina dónde es accesible en el código, y puede ser de bloque, de método o de clase.
🐝