Configuración del entorno y primer programa
Para iniciar con Java es necesario instalar el JDK y configurar las variables de entorno. El JDK (Java Development Kit) contiene el compilador javac, el intérprete java y otras herramientas esenciales.
Configuración de JAVA_HOME
Se recomienda crear la variable de entorno JAVA_HOME apuntando a la carpeta de instalación del JDK, y luego añadir %JAVA_HOME%\bin al PATH del sistema.
Primer programa
public class SaludoMundo {
public static void main(String[] args) {
System.out.println("Hola, mundo!");
}
}
Pasos de compilación y ejecución:
- Guardar el archivo como
SaludoMundo.java - Compilar:
javac SaludoMundo.java - Ejecutar:
java SaludoMundo
Tipos de comentarios
// Comentario de una línea
/*
Comentario
de múltiples líneas
*/
/**
* Comentario de documentación
* que permite generar documentación con javadoc
*/
Diferencia entre println y print
println imprime el texto y agrega un salto de línea al final, mientras que print imprime sin salto de línea.
public class EjemploPrint {
public static void main(String[] args) {
System.out.print("Primero ");
System.out.print("Segundo ");
System.out.println("Tercero"); // salto de línea aquí
System.out.print("Cuarto");
}
}
Conceptos previos de Java
Unidades de almacenamiento
El byte es la unidad mínima de almacenamiento en computación. Las conversiones son:
- 8 bits = 1 Byte
- 1024 B = 1 KB
- 1024 KB = 1 MB
- 1024 MB = 1 GB
- 1024 GB = 1 TB
JVM y portabilidad
La Máquina Virtual de Java (JVM) permite que el código compilado se ejecute en cualquier sistema operativo. Esto se logra porque el código fuente se compila a bytecode (.class), y cada plataforma tiene su propia implementación de la JVM.
Variables y tipos de datos
Constantes
public class ConstantesDemo {
public static void main(String[] args) {
// Constantes numéricas enteras
System.out.println(42);
System.out.println(-7);
// Constantes de punto flotante
System.out.println(3.14);
System.out.println(2.0);
// Constantes de carácter
System.out.println('Z');
System.out.println(' ');
// Constantes de cadena
System.out.println("Aprendiendo Java");
System.out.println("");
// Constantes booleanas
System.out.println(true);
System.out.println(false);
}
}
Declaración de variables
| Tipo | Palabra clave | Memoria | Rango |
|---|---|---|---|
| Byte | byte | 1 byte | -128 a 127 |
| Entero corto | short | 2 bytes | -32768 a 32767 |
| Entero | int | 4 bytes | ±2 mil millones |
| Entero largo | long | 8 bytes | Hasta 19 dígitos |
| Flotante | float | 4 bytes | 7 dígitos decimales |
| Doble | double | 8 bytes | 16 dígitos decimales |
| Carácter | char | 2 bytes | 0 a 65535 |
| Booleano | boolean | 1 byte | true / false |
public class VariablesDemo {
public static void main(String[] args) {
byte edad = 25;
short anio = 2024;
int poblacion = 1000000;
long distancia = 384400L;
float precio = 19.99F;
double pi = 3.14159265;
char inicial = 'A';
boolean activo = true;
String nombre = "María";
System.out.println("Nombre: " + nombre);
System.out.println("Edad: " + edad);
System.out.println("Activo: " + activo);
}
}
Caracteres de escape
public class EscapeDemo {
public static void main(String[] args) {
// Salto de línea
System.out.println("Línea 1\nLínea 2");
// Tabulación
System.out.println("Columna1\tColumna2");
// Ruta con backslash (doble barra)
String ruta = "C:\\Usuarios\\Documentos\\proyecto";
System.out.println(ruta);
}
}
Conversión de tipos de datos
Conversión automática: cuando un tipo con menor rango se asigna a uno con mayor rango.
public class ConversionAuto {
public static void main(String[] args) {
int cantidad = 100;
double resultado = cantidad; // int se convierte a double automáticamente
System.out.println("Resultado: " + resultado);
byte b = 5;
int total = b + 10; // byte se promueve a int
System.out.println("Total: " + total);
}
}
Conversión explícita (casting): cuando se asigna un tipo mayor a uno menor, requiere conversión manual.
public class ConversionExplicita {
public static void main(String[] args) {
double valor = 9.78;
int entero = (int) valor; // truncamiento, pierde la parte decimal
System.out.println("Entero: " + entero); // 9
long grande = 10000000000L;
int pequeno = (int) grande; // posible desbordamiento
System.out.println("Valor truncado: " + pequeno);
// byte con operación requiere casting manual
byte contador = 10;
contador = (byte)(contador + 1);
System.out.println("Contador: " + contador);
}
}
Operadores
Operadores aritméticos
public class OperadoresAritmeticos {
public static void main(String[] args) {
int x = 15;
int y = 4;
System.out.println("Suma: " + (x + y)); // 19
System.out.println("Resta: " + (x - y)); // 11
System.out.println("Multiplicación: " + (x * y)); // 60
System.out.println("División: " + (x / y)); // 3 (entera)
System.out.println("Módulo: " + (x % y)); // 3
// Concatenación con +
String saludo = "Hola" + " " + "Mundo";
System.out.println(saludo);
}
}
Operadores de incremento y decremento
public class IncrementoDemo {
public static void main(String[] args) {
int valor = 10;
// Post-incremento: usa el valor actual, luego incrementa
int resultado1 = valor++;
System.out.println("resultado1 = " + resultado1); // 10
System.out.println("valor = " + valor); // 11
// Pre-incremento: incrementa primero, luego usa el valor
int resultado2 = ++valor;
System.out.println("resultado2 = " + resultado2); // 12
System.out.println("valor = " + valor); // 12
}
}
Operadores de asignación compuesta
public class AsignacionCompuesta {
public static void main(String[] args) {
int cantidad = 50;
cantidad += 10; // cantidad = cantidad + 10 → 60
cantidad -= 5; // cantidad = cantidad - 5 → 55
cantidad *= 2; // cantidad = cantidad * 2 → 110
cantidad /= 3; // cantidad = cantidad / 3 → 36
cantidad %= 7; // cantidad = cantidad % 7 → 1
System.out.println("Cantidad: " + cantidad);
}
}
Operaodres relacionales
public class OperadoresRelacionales {
public static void main(String[] args) {
int a = 15;
int b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a > b); // false
System.out.println(a < b); // true
System.out.println(a >= b); // false
System.out.println(a <= b); // true
}
}
Operadores lógicos
public class OperadoresLogicos {
public static void main(String[] args) {
int edad = 25;
double salario = 5000.0;
// AND lógico (&&): ambos deben ser true
boolean elegible = (edad >= 18) && (salario > 3000);
System.out.println("Elegible: " + elegible); // true
// OR lógico (||): al menos uno debe ser true
boolean especial = (edad > 60) || (salario > 10000);
System.out.println("Especial: " + especial); // false
// NOT lógico (!): invierte el valor booleano
boolean inactivo = !elegible;
System.out.println("Inactivo: " + inactivo); // false
}
}
Operador ternario
public class TernarioDemo {
public static void main(String[] args) {
// Ejemplo 1: verificar si un número es positivo o negativo
int numero = -7;
String signo = (numero >= 0) ? "Positivo" : "Negativo";
System.out.println(numero + " es " + signo);
// Ejemplo 2: obtener el mayor entre tres valores
int p = 40, q = 85, r = 60;
int maximo = (p > q) ? ((p > r) ? p : r) : ((q > r) ? q : r);
System.out.println("El mayor es: " + maximo);
}
}
Entrada por teclado y números aleatorios
Clase Scanner
import java.util.Scanner;
public class EntradaTeclado {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.print("Ingrese su nombre: ");
String nombre = entrada.nextLine();
System.out.print("Ingrese su edad: ");
int edad = entrada.nextInt();
System.out.println("Hola " + nombre + ", tienes " + edad + " años.");
}
}
Nota importante: al combinar next() con nextLine(), se debe llamar a nextLine() adicional para consumir el carácter de salto de línea residual.
Clase Random
import java.util.Random;
public class AleatorioDemo {
public static void main(String[] args) {
Random generador = new Random();
// Número aleatorio entre 0 y 99
int num1 = generador.nextInt(100);
System.out.println("Entre 0 y 99: " + num1);
// Número aleatorio entre 1 y 100
int num2 = generador.nextInt(100) + 1;
System.out.println("Entre 1 y 100: " + num2);
// Número aleatorio entre 50 y 150
int num3 = generador.nextInt(101) + 50;
System.out.println("Entre 50 y 150: " + num3);
}
}
Control de flujo
Estructura switch
import java.util.Scanner;
public class EjemploSwitch {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
System.out.print("Ingrese un día (1-7): ");
int dia = teclado.nextInt();
String nombreDia;
switch (dia) {
case 1:
nombreDia = "Lunes";
break;
case 2:
nombreDia = "Martes";
break;
case 3:
nombreDia = "Miércoles";
break;
case 4:
nombreDia = "Jueves";
break;
case 5:
nombreDia = "Viernes";
break;
case 6:
nombreDia = "Sábado";
break;
case 7:
nombreDia = "Domingo";
break;
default:
nombreDia = "Día inválido";
break;
}
System.out.println("Es " + nombreDia);
}
}
Penetración de cases (fall-through)
public class EstacionesSwitch {
public static void main(String[] args) {
int mes = 7;
String estacion;
switch (mes) {
case 12: case 1: case 2:
estacion = "Invierno";
break;
case 3: case 4: case 5:
estacion = "Primavera";
break;
case 6: case 7: case 8:
estacion = "Verano";
break;
case 9: case 10: case 11:
estacion = "Otoño";
break;
default:
estacion = "Mes inválido";
}
System.out.println("Estación: " + estacion);
}
}
Estructuras if / else if / else
import java.util.Scanner;
public class EjemploElseIf {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
System.out.print("Ingrese su edad: ");
int edad = teclado.nextInt();
String categoria;
if (edad < 0 || edad > 130) {
categoria = "Edad no válida";
} else if (edad <= 6) {
categoria = "Infante";
} else if (edad <= 12) {
categoria = "Niño";
} else if (edad <= 17) {
categoria = "Adolescente";
} else if (edad <= 45) {
categoria = "Joven adulto";
} else if (edad <= 69) {
categoria = "Adulto";
} else {
categoria = "Adulto mayor";
}
System.out.println("Categoría: " + categoria);
}
}
Ciclo for
public class CicloFor {
public static void main(String[] args) {
// Suma de los primeros 100 números
int acumulador = 0;
for (int contador = 1; contador <= 100; contador++) {
acumulador += contador;
}
System.out.println("Suma de 1 a 100: " + acumulador);
// Contar números pares entre 1 y 50
int pares = 0;
for (int i = 1; i <= 50; i++) {
if (i % 2 == 0) {
pares++;
}
}
System.out.println("Cantidad de pares: " + pares);
}
}
Ciclo while
public class EjemploWhile {
public static void main(String[] args) {
// Aproximación: cuántas veces hay que doblar una hoja para alcanzar cierta altura
double grosorHoja = 0.0001; // metros (0.1 mm)
double alturaMeta = 8844.0; // metros (Monte Everest)
int pliegues = 0;
while (grosorHoja < alturaMeta) {
grosorHoja *= 2;
pliegues++;
}
System.out.println("Pliegues necesarios: " + pliegues);
}
}
Ciclo do-while
public class EjemploDoWhile {
public static void main(String[] args) {
int iterador = 0;
do {
System.out.println("Iteración " + iterador);
iterador++;
} while (iterador < 3);
}
}
Palabras clave break y continue
public class BreakContinueDemo {
public static void main(String[] args) {
// break: termina el ciclo completo
for (int i = 0; i < 10; i++) {
if (i == 5) break;
System.out.print(i + " ");
}
System.out.println(); // 0 1 2 3 4
// continue: salta la iteración actual
for (int i = 0; i < 10; i++) {
if (i % 3 == 0) continue;
System.out.print(i + " ");
}
System.out.println(); // 1 2 4 5 7 8
}
}
Ciclos anidados
public class TrianguloEstrellas {
public static void main(String[] args) {
for (int fila = 1; fila <= 5; fila++) {
for (int col = 0; col < fila; col++) {
System.out.print("* ");
}
System.out.println();
}
}
}
Arreglos
Declaración e inicialización
public class ArreglosBasico {
public static void main(String[] args) {
// Inicialización dinámica
int[] numeros = new int[4];
numeros[0] = 10;
numeros[1] = 20;
numeros[2] = 30;
numeros[3] = 40;
// Inicialización estática
String[] frutas = {"Manzana", "Banana", "Naranja", "Uva", "Pera"};
// Obtener longitud
System.out.println("Total de frutas: " + frutas.length);
// Recorrer el arreglo
for (int i = 0; i < frutas.length; i++) {
System.out.println("Fruta[" + i + "] = " + frutas[i]);
}
}
}
Operaciones comunes con arreglos
Encontrar el valor máximo:
public class MaximoArreglo {
public static void main(String[] args) {
int[] datos = {12, 45, 7, 89, 23, 56, 3};
int maximo = datos[0];
for (int i = 1; i < datos.length; i++) {
if (datos[i] > maximo) {
maximo = datos[i];
}
}
System.out.println("Valor máximo: " + maximo);
}
}
Buscar un elemento:
import java.util.Scanner;
public class BuscarElemento {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
int[] coleccion = {15, 28, 42, 57, 63, 79, 84};
System.out.print("Número a buscar: ");
int objetivo = teclado.nextInt();
int posicion = -1;
for (int i = 0; i < coleccion.length; i++) {
if (coleccion[i] == objetivo) {
posicion = i;
break;
}
}
if (posicion != -1) {
System.out.println("Encontrado en posición: " + posicion);
} else {
System.out.println("Elemento no encontrado");
}
}
}
Copiar y redimensionar arreglos:
public class RedimensionarArreglo {
public static void main(String[] args) {
int[] original = {10, 20, 30};
int[] ampliado = new int[7];
for (int i = 0; i < original.length; i++) {
ampliado[i] = original[i];
}
ampliado[3] = 40;
ampliado[4] = 50;
for (int valor : ampliado) {
System.out.print(valor + " ");
}
System.out.println();
}
}
Arreglos bidimensionales
public class ArregloBidimensional {
public static void main(String[] args) {
String[][] tabla = {
{"Ana", "Luis", "María"},
{"Pedro", "Sofía"},
{"Carlos", "Elena", "Raúl", "Laura"}
};
// Recorrer e imprimir todos los elementos
for (int fila = 0; fila < tabla.length; fila++) {
for (int col = 0; col < tabla[fila].length; col++) {
System.out.print(tabla[fila][col] + "\t");
}
System.out.println();
}
}
}
Métodos
Definición y tipos de métodos
Método sin parámetros sin retorno:
public class MetodoSimple {
public static void main(String[] args) {
mostrarSaludo();
mostrarSaludo();
}
public static void mostrarSaludo() {
System.out.println("¡Bienvenido al curso de Java!");
}
}
Método con parámetros sin retorno:
public class MetodoConParametros {
public static void main(String[] args) {
calcularSuma(25, 37);
}
public static void calcularSuma(int a, int b) {
int resultado = a + b;
System.out.println("La suma es: " + resultado);
}
}
Método sin parámetros con retorno:
public class MetodoConRetorno {
public static void main(String[] args) {
int total = sumarCien();
System.out.println("Suma de 1 a 100: " + total);
}
public static int sumarCien() {
int suma = 0;
for (int n = 1; n <= 100; n++) {
suma += n;
}
return suma;
}
}
Método con parámetros y retorno:
import java.util.Scanner;
public class MetodoCompleto {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
System.out.print("Ingrese un número entero: ");
int numero = teclado.nextInt();
String resultado = determinarParidad(numero);
System.out.println("El número " + numero + " es " + resultado);
}
public static String determinarParidad(int num) {
return (num % 2 == 0) ? "par" : "impar";
}
}
Sobrecarga de métodos
public class SobrecargaDemo {
public static void main(String[] args) {
System.out.println(sumar(3, 7)); // 10
System.out.println(sumar(3, 7, 11)); // 21
System.out.println(sumar(3, 7, 11, 15)); // 36
}
public static int sumar(int a, int b) {
return a + b;
}
public static int sumar(int a, int b, int c) {
return a + b + c;
}
public static int sumar(int a, int b, int c, int d) {
return a + b + c + d;
}
}
Parámetros variables (varargs)
public class VarargsDemo {
public static void main(String[] args) {
System.out.println(promedio(80, 90, 70, 85, 95));
}
public static double promedio(double... valores) {
double suma = 0;
for (double v : valores) {
suma += v;
}
return suma / valores.length;
}
}
Recursión
public class RecursionDemo {
public static void main(String[] args) {
System.out.println("Factorial de 5: " + factorial(5)); // 120
System.out.println("Fibonacci[7]: " + fibonacci(7)); // 13
}
// Calcula n! = n * (n-1) * ... * 1
public static long factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Calcula el n-ésimo número de Fibonacci
public static int fibonacci(int n) {
if (n == 1 || n == 2) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
Programación orientada a objetos
Clases y objetos
public class Vehiculo {
// Atributos (miembros de instancia)
String marca;
String modelo;
int anioFabricacion;
double kilometraje;
// Comportamiento (métodos)
public void arrancar() {
System.out.println("El " + marca + " " + modelo + " ha arrancado.");
}
public void detener() {
System.out.println("El vehículo se ha detenido.");
}
public String obtenerInfo() {
return marca + " " + modelo + " (" + anioFabricacion + ") - " + kilometraje + " km";
}
}
public class TestVehiculo {
public static void main(String[] args) {
Vehiculo miAuto = new Vehiculo();
miAuto.marca = "Toyota";
miAuto.modelo = "Corolla";
miAuto.anioFabricacion = 2022;
miAuto.kilometraje = 15000.5;
miAuto.arrancar();
System.out.println(miAuto.obtenerInfo());
miAuto.detener();
}
}
Encapsulamiento
public class CuentaBancaria {
private String titular;
private double saldo;
public CuentaBancaria() {
}
public CuentaBancaria(String titular, double saldoInicial) {
this.titular = titular;
this.saldo = saldoInicial;
}
public String getTitular() {
return titular;
}
public void setTitular(String titular) {
this.titular = titular;
}
public double getSaldo() {
return saldo;
}
public void depositar(double monto) {
if (monto > 0) {
saldo += monto;
System.out.println("Depósito exitoso. Saldo: " + saldo);
} else {
System.out.println("El monto debe ser positivo.");
}
}
public boolean retirar(double monto) {
if (monto > 0 && monto <= saldo) {
saldo -= monto;
System.out.println("Retiro exitoso. Saldo: " + saldo);
return true;
}
System.out.println("Fondos insuficientes o monto inválido.");
return false;
}
}
Variables de instancia vs variables locales
- Variables de instancia: se declaran dentro de la clase pero fuera de cualquier método. Tienen valores predeterminados (0, 0.0, false, null, '\u0000') y su ciclo de vida está ligado al objeto.
- Variables locales: se declaran dentro de un método o bloque. No tienen valor predeterminado y deben inicializarse antes de usarse. Existen solo durante la ejecución del método.
Herencia
// Clase padre
public class Figura {
protected String color;
public Figura(String color) {
this.color = color;
}
public void mostrarColor() {
System.out.println("Color: " + color);
}
public double calcularArea() {
return 0;
}
}
// Clase hija
public class Circulo extends Figura {
private double radio;
public Circulo(String color, double radio) {
super(color);
this.radio = radio;
}
@Override
public double calcularArea() {
return Math.PI * radio * radio;
}
}
public class Rectangulo extends Figura {
private double ancho;
private double alto;
public Rectangulo(String color, double ancho, double alto) {
super(color);
this.ancho = ancho;
this.alto = alto;
}
@Override
public double calcularArea() {
return ancho * alto;
}
}
public class TestFiguras {
public static void main(String[] args) {
Circulo circulo = new Circulo("Rojo", 5.0);
circulo.mostrarColor();
System.out.println("Área del círculo: " + circulo.calcularArea());
Rectangulo rectangulo = new Rectangulo("Azul", 4.0, 6.0);
rectangulo.mostrarColor();
System.out.println("Área del rectángulo: " + rectangulo.calcularArea());
}
}
Clases abstractas
public abstract class Empleado {
private String nombre;
private int edad;
private double salarioBase;
public Empleado() {
}
public Empleado(String nombre, int edad, double salarioBase) {
this.nombre = nombre;
this.edad = edad;
this.salarioBase = salarioBase;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
public double getSalarioBase() {
return salarioBase;
}
public void setSalarioBase(double salarioBase) {
this.salarioBase = salarioBase;
}
// Método abstracto: cada subclase debe implementarlo
public abstract double calcularSalario();
// Método concreto: disponible para todas las subclases
public void mostrarInfo() {
System.out.println("Empleado: " + nombre + ", Edad: " + edad +
", Salario: " + calcularSalario());
}
}
public class EmpleadoTiempoCompleto extends Empleado {
private double bono;
public EmpleadoTiempoCompleto(String nombre, int edad, double salarioBase, double bono) {
super(nombre, edad, salarioBase);
this.bono = bono;
}
@Override
public double calcularSalario() {
return getSalarioBase() + bono;
}
}
public class EmpleadoMedioTiempo extends Empleado {
private double horasTrabajadas;
private double tarifaHora;
public EmpleadoMedioTiempo(String nombre, int edad, double horas, double tarifa) {
super(nombre, edad, 0);
this.horasTrabajadas = horas;
this.tarifaHora = tarifa;
}
@Override
public double calcularSalario() {
return horasTrabajadas * tarifaHora;
}
}
public class TestEmpleados {
public static void main(String[] args) {
EmpleadoTiempoCompleto emp1 = new EmpleadoTiempoCompleto("Ana", 30, 3000, 500);
emp1.mostrarInfo();
EmpleadoMedioTiempo emp2 = new EmpleadoMedioTiempo("Luis", 22, 80, 25);
emp2.mostrarInfo();
}
}
Algoritmos con arreglos
Invertir un arreglo
public class InvertirArreglo {
public static void main(String[] args) {
int[] datos = {10, 20, 30, 40, 50, 60};
for (int izq = 0, der = datos.length - 1; izq < der; izq++, der--) {
int temporal = datos[izq];
datos[izq] = datos[der];
datos[der] = temporal;
}
for (int valor : datos) {
System.out.print(valor + " ");
}
System.out.println();
}
}
Ordenamiento burbuja
public class OrdenamientoBurbuja {
public static void main(String[] args) {
int[] arreglo = {64, 25, 12, 22, 11};
int n = arreglo.length;
for (int pasada = 0; pasada < n - 1; pasada++) {
for (int i = 0; i < n - 1 - pasada; i++) {
if (arreglo[i] > arreglo[i + 1]) {
int temp = arreglo[i];
arreglo[i] = arreglo[i + 1];
arreglo[i + 1] = temp;
}
}
}
System.out.print("Ordenado: ");
for (int val : arreglo) {
System.out.print(val + " ");
}
System.out.println();
}
}
Búsqueda binaria
public class BusquedaBinaria {
public static void main(String[] args) {
int[] ordenado = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
int indice = buscarBinario(ordenado, 23);
System.out.println("Elemento encontrado en índice: " + indice);
}
public static int buscarBinario(int[] arr, int objetivo) {
int inicio = 0;
int fin = arr.length - 1;
while (inicio <= fin) {
int medio = (inicio + fin) / 2;
if (arr[medio] == objetivo) {
return medio;
} else if (objetivo < arr[medio]) {
fin = medio - 1;
} else {
inicio = medio + 1;
}
}
return -1; // No encontrado
}
}
Arreglo de objetos
public class Estudiante {
private String nombre;
private double calificacion;
public Estudiante(String nombre, double calificacion) {
this.nombre = nombre;
this.calificacion = calificacion;
}
public String getNombre() {
return nombre;
}
public double getCalificacion() {
return calificacion;
}
}
public class TestArregloObjetos {
public static void main(String[] args) {
Estudiante[] grupo = new Estudiante[4];
grupo[0] = new Estudiante("Roberto", 8.5);
grupo[1] = new Estudiante("Carmen", 9.2);
grupo[2] = new Estudiante("Diego", 7.8);
grupo[3] = new Estudiante("Lucía", 9.8);
// Ordenar por calificación (burbuja)
for (int i = 0; i < grupo.length - 1; i++) {
for (int j = 0; j < grupo.length - 1 - i; j++) {
if (grupo[j].getCalificacion() > grupo[j + 1].getCalificacion()) {
Estudiante temp = grupo[j];
grupo[j] = grupo[j + 1];
grupo[j + 1] = temp;
}
}
}
for (Estudiante e : grupo) {
System.out.println(e.getNombre() + " → " + e.getCalificacion());
}
}
}
Clases utilitarias y la palabra static
Miembros estáticos
public class ConfiguracionGlobal {
// Variable estática: compartida por todas las instancias
static String idioma = "es";
static int maximoConexiones = 100;
// Método estático: se invoca directamente con el nombre de la clase
public static void mostrarConfig() {
System.out.println("Idioma: " + idioma);
System.out.println("Máximo conexiones: " + maximoConexiones);
}
}
public class TestConfig {
public static void main(String[] args) {
// No es necesario crear objeto
ConfiguracionGlobal.mostrarConfig();
ConfiguracionGlobal.idioma = "en";
ConfiguracionGlobal.mostrarConfig();
}
}
Clases utilitarias
// Clase utilitaria: constructor privado, todos los métodos son estáticos
public final class MatematicasUtils {
private MatematicasUtils() {
// Evita la instanciación
}
public static int maximo(int a, int b) {
return (a > b) ? a : b;
}
public static int minimo(int a, int b) {
return (a < b) ? a : b;
}
public static boolean esPrimo(int numero) {
if (numero <= 1) return false;
for (int i = 2; i <= Math.sqrt(numero); i++) {
if (numero % i == 0) return false;
}
return true;
}
public static long factorial(int n) {
long resultado = 1;
for (int i = 2; i <= n; i++) {
resultado *= i;
}
return resultado;
}
}
public class TestUtils {
public static void main(String[] args) {
System.out.println("Max(10, 20): " + MatematicasUtils.maximo(10, 20));
System.out.println("¿17 es primo? " + MatematicasUtils.esPrimo(17));
System.out.println("6! = " + MatematicasUtils.factorial(6));
}
}
Paso de parámetros
public class PasoParametros {
public static void main(String[] args) {
// Tipos primitivos: se pasa una copia del valor
int numero = 10;
duplicar(numero);
System.out.println("numero después: " + numero); // sigue siendo 10
// Tipos de referencia: se pasa la dirección de memoria
int[] arreglo = {1, 2, 3};
multiplicarPorDos(arreglo);
System.out.println("arreglo[0] después: " + arreglo[0]); // 2
}
public static void duplicar(int valor) {
valor *= 2;
System.out.println("valor dentro del método: " + valor); // 20
}
public static void multiplicarPorDos(int[] arr) {
for (int i = 0; i < arr.length; i++) {
arr[i] *= 2;
}
}
}
Caso práctico: sistema de empleados con herencia
public abstract class EmpleadoBase {
private int idEmpleado;
private String nombreCompleto;
public EmpleadoBase() {
}
public EmpleadoBase(int idEmpleado, String nombreCompleto) {
this.idEmpleado = idEmpleado;
this.nombreCompleto = nombreCompleto;
}
public int getIdEmpleado() {
return idEmpleado;
}
public String getNombreCompleto() {
return nombreCompleto;
}
public abstract void trabajar();
}
public abstract class Desarrollador extends EmpleadoBase {
public Desarrollador() {
}
public Desarrollador(int id, String nombre) {
super(id, nombre);
}
}
public class IngenieroJava extends Desarrollador {
public IngenieroJava() {
}
public IngenieroJava(int id, String nombre) {
super(id, nombre);
}
@Override
public void trabajar() {
System.out.println("Empleado #" + getIdEmpleado() + " (" + getNombreCompleto()
+ ") está desarrollando una aplicación web.");
}
}
public class IngenieroMovil extends Desarrollador {
public IngenieroMovil() {
}
public IngenieroMovil(int id, String nombre) {
super(id, nombre);
}
@Override
public void trabajar() {
System.out.println("Empleado #" + getIdEmpleado() + " (" + getNombreCompleto()
+ ") está creando una aplicación móvil.");
}
}
public abstract class Mantenimiento extends EmpleadoBase {
public Mantenimiento() {
}
public Mantenimiento(int id, String nombre) {
super(id, nombre);
}
}
public class TecnicoRedes extends Mantenimiento {
public TecnicoRedes() {
}
public TecnicoRedes(int id, String nombre) {
super(id, nombre);
}
@Override
public void trabajar() {
System.out.println("Empleado #" + getIdEmpleado() + " (" + getNombreCompleto()
+ ") está verificando la conectividad de red.");
}
}
public class TecnicoHardware extends Mantenimiento {
public TecnicoHardware() {
}
public TecnicoHardware(int id, String nombre) {
super(id, nombre);
}
@Override
public void trabajar() {
System.out.println("Empleado #" + getIdEmpleado() + " (" + getNombreCompleto()
+ ") está reparando componentes de hardware.");
}
}
public class TestEmpresa {
public static void main(String[] args) {
IngenieroJava dev1 = new IngenieroJava(101, "Carlos Méndez");
dev1.trabajar();
IngenieroMovil dev2 = new IngenieroMovil(102, "Laura Gómez");
dev2.trabajar();
TecnicoRedes red = new TecnicoRedes(201, "Pedro Sánchez");
red.trabajar();
TecnicoHardware hw = new TecnicoRedes(202, "Ana Torres");
hw.trabajar();
}
}