Tu ruta para dominar
Java desde cero
Este es tu curso personal, diseñado a medida según tu código actual en GitHub. Aprenderás con explicaciones simples, analogías reales y ejercicios prácticos con soluciones.
Revisé tus repos AdvancedCalculator y RPG-Console-Simulator. Ya dominas: Scanner, métodos estáticos, switch, do-while, Math.pow, Math.sqrt. ¡Eso es una base sólida! Ahora te llevaré al siguiente nivel: Arrays, POO, Herencia y Colecciones.
¿Qué es Java?
Cómo funciona y por qué existe
Variables y Tipos
int, double, String, boolean...
Operadores
Aritméticos, lógicos, comparación
Condicionales
if, else, switch
Bucles
for, while, do-while
Métodos
Tú ya lo haces en tu calculadora ✅
Scanner
Entrada del usuario ✅
Arrays
Guardar múltiples valores 🚀
POO: Clases
El corazón de Java 🚀
Herencia
Reutilizar código 🚀
ArrayList
Listas dinámicas 🚀
Excepciones
Manejar errores 🚀
¿Qué es Java?
☕ Java en una frase
Java es un lenguaje de programación que le dice a la computadora qué hacer, paso a paso. Se usa para apps Android, sistemas bancarios, videojuegos (Minecraft) y mucho más.
Imagina que la computadora es un chef que no habla tu idioma. Java es el idioma intermediario: tú escribes las instrucciones en Java, y Java se las traduce a la computadora en un lenguaje que ella entiende.
🔄 ¿Cómo funciona?
Tú escribes código → javac lo compila → se crea un archivo .class → la JVM (Java Virtual Machine) lo ejecuta en cualquier computadora.
📄 Tu primer programa Java
public class HolaMundo { public static void main(String[] args) { // Esto le dice a la pantalla que imprima un texto System.out.println("¡Hola, Mundo!"); } }
System.out.println() es como decirle a Java: "oye, imprime esto en la pantalla". El texto entre comillas " " es lo que aparecerá.
Tu presentación en pantalla
Escribe un programa que imprima en pantalla: tu nombre, tu edad y lo que quieres lograr aprendiendo Java. Cada cosa en una línea separada.
📌 Ejemplo de salida esperada:
Mi nombre es Ana
Tengo 22 años
Quiero crear apps para Android
public class Presentacion { public static void main(String[] args) { System.out.println("Mi nombre es Ana"); System.out.println("Tengo 22 años"); System.out.println("Quiero crear apps para Android"); } }
Cada println pone el cursor en una nueva línea automáticamente. Si usas print (sin la "ln"), todo quedará en la misma línea.
Variables y Tipos de Datos
Una variable es como una caja etiquetada. La caja tiene un nombre (ej: edad), un tipo (lo que puede guardar, ej: solo números enteros), y un contenido (el valor, ej: 22).
📊 Los tipos más importantes
| Tipo | ¿Para qué? | Ejemplo |
|---|---|---|
| int | Números enteros | int edad = 22; |
| double | Números con decimales | double precio = 9.99; |
| String | Texto | String nombre = "Ana"; |
| boolean | Verdadero/Falso | boolean vivo = true; |
| char | Un solo carácter | char letra = 'A'; |
public class Variables { public static void main(String[] args) { // Declarar y asignar variables int edad = 22; double altura = 1.75; String nombre = "Ana"; boolean estudia = true; // Usar las variables System.out.println("Nombre: " + nombre); System.out.println("Edad: " + edad); System.out.println("Altura: " + altura); System.out.println("¿Estudia?: " + estudia); } }
El + entre un texto y una variable los une. "Edad: " + edad produce "Edad: 22". Esto se llama concatenación.
¡Cuidado! En Java, los tipos importan. No puedes guardar texto en un int ni un número decimal en un int sin perder la parte decimal.
Ficha de personaje RPG
Crea variables para describir un personaje de un juego RPG (ya hiciste un RPG en GitHub 😉). Necesitas: nombre, nivel, vida (con decimales), y si está vivo.
📌 Salida esperada:
Personaje: Shadowblade
Nivel: 5
Vida: 87.5
¿Vivo?: true
public class PersonajeRPG { public static void main(String[] args) { String nombre = "Shadowblade"; int nivel = 5; double vida = 87.5; boolean vivo = true; System.out.println("Personaje: " + nombre); System.out.println("Nivel: " + nivel); System.out.println("Vida: " + vida); System.out.println("¿Vivo?: " + vivo); } }
Operadores
🔢 Operadores Aritméticos
| Operador | Significado | Ejemplo | Resultado |
|---|---|---|---|
| + | Suma | 5 + 3 | 8 |
| - | Resta | 10 - 4 | 6 |
| * | Multiplicación | 3 * 4 | 12 |
| / | División | 10 / 2 | 5 |
| % | Módulo (residuo) | 10 % 3 | 1 |
⚖️ Operadores de Comparación (retornan boolean)
| Operador | Significado | Ejemplo | Resultado |
|---|---|---|---|
| == | ¿Es igual? | 5 == 5 | true |
| != | ¿Es diferente? | 5 != 3 | true |
| > | Mayor que | 8 > 3 | true |
| < | Menor que | 2 < 7 | true |
| >= | Mayor o igual | 5 >= 5 | true |
🧠 Operadores Lógicos
| Operador | Significado | Ejemplo |
|---|---|---|
| && | Y (ambos true) | edad >= 18 && tieneId == true |
| || | O (uno true basta) | esMiembro || pagó |
| ! | Negación | !vivo (si vivo=true → false) |
El módulo (%) ya lo usas en tu calculadora. Sirve para saber si un número es par: numero % 2 == 0 significa que es par.
Calculadora básica mejorada
Declara dos variables a = 15 y b = 4. Luego imprime: la suma, la resta, la multiplicación, la división (con decimales), el módulo, si a es mayor que b, y si ambos son positivos.
📌 Salida esperada:
Suma: 19 Resta: 11 Multiplicación: 60
División: 3.75 Módulo: 3
¿a > b?: true ¿Ambos positivos?: true
public class Operadores { public static void main(String[] args) { int a = 15; int b = 4; System.out.println("Suma: " + (a + b)); System.out.println("Resta: " + (a - b)); System.out.println("Multiplicación: " + (a * b)); System.out.println("División: " + (double) a / b); System.out.println("Módulo: " + (a % b)); System.out.println("¿a > b?: " + (a > b)); System.out.println("¿Ambos positivos?: " + (a > 0 && b > 0)); } }
El truco (double) a / b se llama casting: convierte temporalmente a a decimal para que la división no pierda los decimales.
Condicionales: if, else, switch
Es como un semáforo: si está en verde → avanza. Si no, si está en amarillo → precaución. Si no → detente. El programa toma decisiones igual.
🔵 if / else if / else
int edad = 17; if (edad >= 18) { System.out.println("Puedes entrar"); } else if (edad >= 15) { System.out.println("Entra solo con un adulto"); } else { System.out.println("No puedes entrar"); } // Output: "Entra solo con un adulto"
🔵 switch — Perfecto para menús (ya lo usas en tu calculadora)
int dia = 3; switch (dia) { case 1 -> System.out.println("Lunes"); case 2 -> System.out.println("Martes"); case 3 -> System.out.println("Miércoles"); default -> System.out.println("Otro día"); } // Output: "Miércoles"
Sistema de notas escolar
Dado un puntaje del 0 al 100, imprime si el estudiante: Reprueba (<60), Aprueba (60-74), Bien (75-89), o Excelente (90-100).
📌 Con int puntaje = 83 → debe imprimir: Resultado: Bien
public class Notas { public static void main(String[] args) { int puntaje = 83; String resultado; if (puntaje >= 90) { resultado = "Excelente"; } else if (puntaje >= 75) { resultado = "Bien"; } else if (puntaje >= 60) { resultado = "Aprueba"; } else { resultado = "Reprueba"; } System.out.println("Resultado: " + resultado); } }
Bucles: for, while, do-while
Un bucle es como una lavadora: repite el ciclo de lavado X veces hasta que la ropa esté limpia. En Java, repetimos instrucciones hasta que se cumpla una condición.
🔵 for — Cuando sabes cuántas veces repetir
// Contar del 1 al 5 for (int i = 1; i <= 5; i++) { System.out.println("Número: " + i); } // i=1 → imprime → i se vuelve 2 → imprime → ... → i=6 → para
🔵 while — Cuando no sabes cuántas veces
int vida = 100; while (vida > 0) { vida -= 25; // vida = vida - 25 System.out.println("Vida restante: " + vida); } // 75, 50, 25, 0 → para porque vida ya no es > 0
🔵 do-while — Se ejecuta AL MENOS una vez (ya lo usas en tu calculadora)
int intentos = 0; do { System.out.println("Intento número: " + (intentos + 1)); intentos++; } while (intentos < 3); // Imprime: Intento 1, 2, 3
Tabla de multiplicar
Usando un bucle for, imprime la tabla de multiplicar del número 7 (del 1 al 10).
📌 Salida esperada:7 x 1 = 77 x 2 = 14
...7 x 10 = 70
public class TablaMultiplicar { public static void main(String[] args) { int numero = 7; for (int i = 1; i <= 10; i++) { System.out.println(numero + " x " + i + " = " + (numero * i)); } } }
Métodos y Funciones
¡Ya dominas esto! Tu calculadora usa métodos como sumar(), dividir(), leerNumero(). Esta lección profundiza el concepto para que lo entiendas aún mejor.
Un método es como una receta de cocina: le das ingredientes (parámetros), sigue los pasos, y te devuelve el platillo (return). Puedes usar la receta cuantas veces quieras sin reescribirla.
📐 Anatomía de un método
// [acceso] [tipo retorno] [nombre] ([parámetros]) public static int sumar (int a, int b) { return a + b; // Devuelve el resultado } // Si no devuelve nada, el tipo es "void" public static void saludar (String nombre) { System.out.println("Hola, " + nombre); } // Llamar los métodos desde main: int resultado = sumar(3, 4); // resultado = 7 saludar("Ana"); // imprime "Hola, Ana"
Calculadora de daño RPG
Crea un método calcularDanio que reciba el ataque y la defensa del enemigo, y retorne el daño real (ataque - defensa, mínimo 0). Luego crea otro método estaVivo que reciba la vida y retorne true si es mayor que 0.
📌 Prueba con: ataque=45, defensa=20, vida=30
→ Daño causado: 25 / ¿Sigue vivo?: true
public class DanioRPG { public static int calcularDanio(int ataque, int defensa) { int danio = ataque - defensa; return danio > 0 ? danio : 0; } public static boolean estaVivo(int vida) { return vida > 0; } public static void main(String[] args) { int danio = calcularDanio(45, 20); int vida = 30; System.out.println("Daño causado: " + danio); System.out.println("¿Sigue vivo?: " + estaVivo(vida)); } }
El danio > 0 ? danio : 0 es el operador ternario: una forma corta de escribir un if-else de una línea. Lee: "si danio > 0, retorna danio, si no, retorna 0".
Scanner — Entrada del Usuario
Ya usas Scanner perfectamente en tu calculadora. Aquí aprenderás los métodos más útiles y el truco del nextLine() que a veces falla.
import java.util.Scanner; public class EntradaUsuario { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Tu nombre: "); String nombre = sc.nextLine(); // Lee texto System.out.print("Tu edad: "); int edad = sc.nextInt(); // Lee entero System.out.print("Tu altura: "); double altura = sc.nextDouble(); // Lee decimal sc.close(); System.out.println("Hola " + nombre + ", " + edad + " años, " + altura + "m"); } }
El bug más común: Si usas nextInt() y luego nextLine(), el primer nextLine() captura el ENTER que dejó nextInt. Solución: agrega un sc.nextLine() vacío entre ellos. ¡Ya lo haces en tu calculadora con ese bloque de ENTER!
Registro de jugador interactivo
Pide al usuario: nombre del personaje, nivel inicial, y clase (guerrero/mago/arquero). Luego muestra un resumen con esa info.
📌 Ejemplo de interacción:Nombre de tu personaje: KaelNivel inicial (1-5): 3Clase: Mago--- PERSONAJE CREADO ---Kael | Nivel 3 | Clase: Mago
import java.util.Scanner; public class RegistroJugador { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Nombre de tu personaje: "); String nombre = sc.nextLine(); System.out.print("Nivel inicial (1-5): "); int nivel = sc.nextInt(); sc.nextLine(); // limpiar el ENTER System.out.print("Clase: "); String clase = sc.nextLine(); System.out.println("--- PERSONAJE CREADO ---"); System.out.println(nombre + " | Nivel " + nivel + " | Clase: " + clase); sc.close(); } }
Arrays — Guardar múltiples valores
Hasta ahora guardabas un valor en una variable, como poner un libro en una caja. Un array es una estantería: guarda muchos libros en orden, y cada uno tiene su número de posición (índice, empezando desde 0).
📐 Crear y usar arrays
// Crear un array de 5 enteros int[] numeros = {10, 20, 30, 40, 50}; // 0 1 2 3 4 ← índices System.out.println(numeros[0]); // 10 (primer elemento) System.out.println(numeros[2]); // 30 (tercer elemento) System.out.println(numeros.length); // 5 (tamaño) // Recorrer un array con for for (int i = 0; i < numeros.length; i++) { System.out.println("Posición " + i + ": " + numeros[i]); } // For-each: más simple cuando no necesitas el índice for (int n : numeros) { System.out.println(n); }
¡Cuidado con los índices! Un array de 5 elementos tiene índices del 0 al 4. Si intentas acceder a numeros[5], Java lanzará un error ArrayIndexOutOfBoundsException.
🗃️ Array de Strings
String[] jugadores = {"Ana", "Luis", "Marta"}; for (String j : jugadores) { System.out.println("Jugador: " + j); }
Inventario del personaje RPG
Crea un array con 5 ítems del inventario de tu personaje. Luego imprime todos los ítems con su número de posición, y al final imprime cuántos ítems tiene en total.
📌 Salida esperada:[0] Espada de fuego[1] Escudo de roble...Total de ítems: 5
public class InventarioRPG { public static void main(String[] args) { String[] inventario = { "Espada de fuego", "Escudo de roble", "Poción de vida", "Arco élfico", "Mapa del tesoro" }; System.out.println("=== INVENTARIO ==="); for (int i = 0; i < inventario.length; i++) { System.out.println("[" + i + "] " + inventario[i]); } System.out.println("Total de ítems: " + inventario.length); } }
POO: Clases y Objetos
Una Clase es como el plano de una casa. Define cómo será: cuántos cuartos, cuántos baños. Un Objeto es la casa real construida a partir de ese plano. Puedes construir 100 casas del mismo plano, todas distintas pero con la misma estructura.
🏗️ Crear una Clase
public class Personaje { // ATRIBUTOS (características del personaje) String nombre; int nivel; double vida; String clase; // CONSTRUCTOR (se llama cuando creas el objeto) public Personaje(String nombre, int nivel, double vida, String clase) { this.nombre = nombre; this.nivel = nivel; this.vida = vida; this.clase = clase; } // MÉTODOS (acciones que puede hacer) public void atacar(int danio) { System.out.println(nombre + " ataca causando " + danio + " de daño!"); } public void mostrarInfo() { System.out.println("--- " + nombre + " ---"); System.out.println("Nivel: " + nivel + " | Vida: " + vida + " | Clase: " + clase); } }
🧱 Crear Objetos desde la clase
public class Main { public static void main(String[] args) { // Crear objetos (instanciar la clase) Personaje heroe = new Personaje("Kael", 5, 100.0, "Mago"); Personaje villano = new Personaje("Valdris", 8, 150.0, "Guerrero"); // Usar los métodos heroe.mostrarInfo(); heroe.atacar(35); villano.mostrarInfo(); villano.atacar(60); } }
La palabra clave this dentro del constructor se refiere al objeto que se está creando. this.nombre = nombre significa: "el atributo nombre de este objeto = el parámetro nombre que recibí".
Clase Calculadora con POO
Transforma tu calculadora actual en una clase. Crea una clase Calculadora con un atributo historial (String), y métodos sumar, restar, multiplicar y dividir que retornen el resultado Y guarden en el historial la operación realizada.
📌 Pista de estructura:Calculadora calc = new Calculadora();System.out.println(calc.sumar(5, 3)); // 8System.out.println(calc.historial); // "5+3=8"
public class Calculadora { String historial = ""; public double sumar(double a, double b) { double resultado = a + b; historial += a + "+" + b + "=" + resultado + "\n"; return resultado; } public double dividir(double a, double b) { if (b == 0) { System.out.println("Error: no se divide por cero"); return 0; } double resultado = a / b; historial += a + "/" + b + "=" + resultado + "\n"; return resultado; } public static void main(String[] args) { Calculadora calc = new Calculadora(); System.out.println(calc.sumar(5, 3)); System.out.println(calc.dividir(10, 2)); System.out.println("Historial:\n" + calc.historial); } }
Herencia y Polimorfismo
La herencia es como la biología: un Perro hereda de Animal. Ya tiene los comportamientos de Animal (respirar, comer), pero además añade los suyos propios (ladrar). No hay que reescribir lo básico.
// Clase PADRE (base) public class Personaje { String nombre; int vida; public Personaje(String nombre, int vida) { this.nombre = nombre; this.vida = vida; } public void atacar() { System.out.println(nombre + " ataca básicamente"); } } // Clase HIJA — hereda de Personaje public class Mago extends Personaje { int mana; public Mago(String nombre, int vida, int mana) { super(nombre, vida); // llama al constructor del padre this.mana = mana; } // @Override — reescribe el método del padre @Override public void atacar() { System.out.println(nombre + " lanza una bola de fuego! 🔥 (-" + mana/2 + " mana)"); mana -= mana/2; } } // USO: Mago kael = new Mago("Kael", 80, 200); kael.atacar(); // Usa el método del Mago, no el del Personaje
Sistema de personajes RPG con herencia
Crea una clase padre Personaje y tres clases hija: Guerrero, Mago, y Arquero. Cada una con su propio método atacar() diferente. Luego crea un objeto de cada tipo y haz que ataquen.
📌 Salida esperada:Thor golpea con su hacha! ⚔️Kael lanza rayo! ⚡Lyra dispara una flecha! 🏹
class Personaje { String nombre; public Personaje(String n) { nombre = n; } public void atacar() { System.out.println(nombre + " ataca"); } } class Guerrero extends Personaje { public Guerrero(String n) { super(n); } @Override public void atacar() { System.out.println(nombre + " golpea con su hacha! ⚔️"); } } class Mago extends Personaje { public Mago(String n) { super(n); } @Override public void atacar() { System.out.println(nombre + " lanza rayo! ⚡"); } } class Arquero extends Personaje { public Arquero(String n) { super(n); } @Override public void atacar() { System.out.println(nombre + " dispara una flecha! 🏹"); } } public class SistemaRPG { public static void main(String[] args) { Guerrero g = new Guerrero("Thor"); Mago m = new Mago("Kael"); Arquero a = new Arquero("Lyra"); g.atacar(); m.atacar(); a.atacar(); } }
Esto es Polimorfismo: el mismo método atacar() se comporta diferente según el tipo de personaje. Es uno de los conceptos más poderosos de Java.
ArrayList — Listas Dinámicas
Un array normal es como una lista de papel con espacios fijos. Un ArrayList es como una lista de papel infinita: puedes agregar, borrar y buscar elementos libremente, sin definir el tamaño al inicio.
import java.util.ArrayList; public class ListaPersonajes { public static void main(String[] args) { // Crear lista de Strings ArrayList<String> equipo = new ArrayList<>(); // Agregar elementos equipo.add("Kael"); equipo.add("Thor"); equipo.add("Lyra"); // Tamaño System.out.println("Equipo: " + equipo.size() + " miembros"); // Recorrer for (String miembro : equipo) { System.out.println("- " + miembro); } // Acceder por índice System.out.println("Líder: " + equipo.get(0)); // Eliminar equipo.remove("Thor"); System.out.println("Después de bajas: " + equipo); // ¿Contiene? System.out.println("¿Lyra en el equipo?: " + equipo.contains("Lyra")); } }
Lista de hechizos del mago
Crea un ArrayList<String> de hechizos. Agrega 4 hechizos, muéstralos todos, luego elimina el segundo, y muestra la lista final.
📌 Hechizos: "Bola de fuego", "Rayo gélido", "Tormenta arcana", "Escudo mágico"
→ Eliminar el de índice 1 (Rayo gélido)
→ Mostrar lista final de 3 hechizos
import java.util.ArrayList; public class ListaHechizos { public static void main(String[] args) { ArrayList<String> hechizos = new ArrayList<>(); hechizos.add("Bola de fuego"); hechizos.add("Rayo gélido"); hechizos.add("Tormenta arcana"); hechizos.add("Escudo mágico"); System.out.println("Hechizos conocidos:"); for (String h : hechizos) { System.out.println(" ✨ " + h); } hechizos.remove(1); // elimina por índice System.out.println("\nTras olvidar Rayo gélido:"); for (String h : hechizos) { System.out.println(" ✨ " + h); } } }
Manejo de Excepciones
Una excepción es cuando algo sale mal. Como cuando intentas dividir entre 0 — la calculadora no puede hacerlo. En lugar de que el programa explote, usamos try-catch para atrapar el error y manejarlo elegantemente, como un net de seguridad.
import java.util.Scanner; public class Excepciones { public static void main(String[] args) { Scanner sc = new Scanner(System.in); try { // Código que podría fallar System.out.print("Ingresa un número: "); int num = Integer.parseInt(sc.nextLine()); System.out.println("El doble es: " + (num * 2)); } catch (NumberFormatException e) { // Si el usuario escribe texto en vez de número System.out.println("❌ Error: eso no es un número válido"); } finally { // Esto SIEMPRE se ejecuta, haya error o no System.out.println("Programa terminado."); sc.close(); } } }
🚨 Excepciones más comunes
| Excepción | Cuándo ocurre |
|---|---|
| NumberFormatException | Convertir texto no numérico a int/double |
| ArrayIndexOutOfBoundsException | Acceder a índice que no existe en array |
| NullPointerException | Usar un objeto que es null |
| ArithmeticException | División por cero con enteros |
Calculadora robusta con excepciones
Mejora tu calculadora para que use try-catch: si el usuario escribe letras en vez de números, muestra un mensaje de error y vuelve a pedir el número (sin que el programa explote).
📌 Si el usuario escribe "abc" cuando se pide un número → ❌ Por favor ingresa solo números → vuelve a pedir
import java.util.Scanner; public class CalculadoraRobusta { public static double leerNumeroSeguro(Scanner sc, String mensaje) { while (true) { try { System.out.print(mensaje); return Double.parseDouble(sc.nextLine()); } catch (NumberFormatException e) { System.out.println("❌ Por favor ingresa solo números"); } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); double a = leerNumeroSeguro(sc, "Primer número: "); double b = leerNumeroSeguro(sc, "Segundo número: "); System.out.println("Suma: " + (a + b)); System.out.println("Resta: " + (a - b)); if (b != 0) { System.out.println("División: " + (a / b)); } else { System.out.println("❌ No se puede dividir por cero"); } sc.close(); } }
¡Felicidades! Con esto ya tienes un nivel sólido de Java. El siguiente paso es seguir construyendo proyectos: una tienda, un sistema de gestión, un juego más complejo. ¡Cada proyecto enseña más que cualquier tutorial!