Computing">
Guía Completa de Programación en Java
Guía Completa de Programación en Java
INICIACION
javac -version
[Link]("¡Hola, mundo!");
2. Abrir una terminal o símbolo del sistema, ubicarse en el directorio donde está el archivo.
3. Compilar el programa con el comando:
javac [Link]
Errores comunes:
• No poner el mismo nombre de archivo que el nombre de la clase pública.
• Olvidar configurar correctamente el PATH.
• Escribir mal los comandos (java vs javac).
Conclusión del capítulo:
En este capítulo hemos introducido el lenguaje Java, repasando su historia, sus características más
importantes, los tipos de aplicaciones que se pueden desarrollar y cómo instalar el entorno de
desarrollo. También aprendimos a compilar y ejecutar un programa básico desde la línea de
comandos. Estos conocimientos básicos sientan las bases para avanzar hacia conceptos más
complejos en el desarrollo con Java.
Capítulo 2: Fundamentos del lenguaje Java
2.1 Tipos de datos primitivos
Java es un lenguaje fuertemente tipado, lo que significa que cada variable debe declararse con un
tipo específico. Existen ocho tipos de datos primitivos en Java:
• byte: Entero de 8 bits. Rango: -128 a 127.
• long: Entero de 64 bits. Se usa para números grandes. Se indica con una L al final.
Ejemplos:
int edad = 25;
float precio = 19.99f;
char inicial = 'A';
boolean activo = true;
Las constantes son variables cuyo valor no puede cambiar una vez asignado. Se declaran usando
final:
final double PI = 3.1416;
• - Resta
• * Multiplicación
• / División
Ejemplo:
int resultado = 10 + 5; // 15
• Relacionales:
• == Igual a
• != Distinto de
Ejemplo:
boolean mayor = 5 > 3; // true
• Lógicos:
• && AND lógico
• || OR lógico
• ! NOT lógico
Ejemplo:
boolean resultado = (5 > 3) && (4 < 10); // true
Conversión explícita:
double a = 9.7;
int b = (int) a; // b será 9
• switch:
int dia = 3;
switch (dia) {
case 1:
[Link]("Lunes");
break;
case 2:
[Link]("Martes");
break;
default:
[Link]("Otro día");
}
• while:
int i = 0;
while (i < 5) {
[Link](i);
i++;
}
• do-while:
int j = 0;
do {
[Link](j);
j++;
} while (j < 5);
• for:
for (int k = 0; k < 5; k++) {
[Link](k);
}
Ejemplo:
boolean esPar = (numero % 2 == 0);
Operador ternario:
int edad = 20;
String mensaje = (edad >= 18) ? "Adulto" : "Menor";
}
public class Principal {
public static void main(String[] args) {
Persona p1 = new Persona();
[Link] = "Ana";
[Link] = 30;
[Link]();
}
}
En este ejemplo, "Persona" es una clase con dos atributos y un método. Luego se crea un objeto
"p1" de tipo Persona.
3.2 CONSTRUCTORES
Un constructor es un método especial que se ejecuta al crear un objeto. Se usa para inicializar los
atributos. Tiene el mismo nombre que la clase y no tiene tipo de retorno.
Ejemplo:
class Persona {
String nombre;
int edad;
Persona(String nom, int ed) {
nombre = nom;
edad = ed;
}
void mostrar() {
[Link](nombre + " tiene " + edad + " años.");
}
}
public class Principal {
public static void main(String[] args) {
Persona p = new Persona("Luis", 25);
[Link]();
}
}
void mostrarVelocidad() {
[Link]("Velocidad actual: " + velocidad);
}
3.4 ENCAPSULAMIENTO
El encapsulamiento consiste en ocultar los detalles internos de una clase y exponer sólo lo necesario
a través de métodos públicos. Se logra usando modificadores de acceso y métodos getters y setters.
Ejemplo:
class CuentaBancaria {
private double saldo;
public void depositar(double cantidad) {
if (cantidad > 0) saldo += cantidad;
}
}
3.5 MODIFICADORES DE ACCESO
Java define modificadores que controlan la visibilidad de los elementos de una clase:
• public: accesible desde cualquier clase.
• private: accesible solo dentro de la clase.
• protected: accesible en la clase, en el paquete y en subclases.
• sin modificador (default): accesible solo dentro del mismo paquete.
Ejemplo:
class Ejemplo {
public int publico;
private int privado;
protected int protegido;
int paquete;
}
3.6 HERENCIA
La herencia permite que una clase herede atributos y métodos de otra clase. Se usa la palabra clave
"extends".
Ejemplo:
class Animal {
void comer() {
[Link]("El animal come");
}
}
class Perro extends Animal {
void ladrar() {
[Link]("El perro ladra");
}
}
public class Principal {
public static void main(String[] args) {
Perro p = new Perro();
[Link]();
[Link]();
}
}
3.7 POLIMORFISMO
El polimorfismo permite que un mismo método se comporte de manera diferente según el objeto
que lo invoque.
Ejemplo:
class Animal {
void hacerSonido() {
[Link]("Sonido genérico");
}
}
class Gato extends Animal {
void hacerSonido() {
[Link]("Miau");
}
}
class Vaca extends Animal {
void hacerSonido() {
[Link]("Muu");
}
}
public class Principal {
public static void main(String[] args) {
Animal a1 = new Gato();
Animal a2 = new Vaca();
[Link]();
[Link]();
}
}
}
Ejemplo de constructores sobrecargados:
class Persona {
String nombre;
int edad;
Persona() {
nombre = "Sin nombre";
edad = 0;
}
Persona(String nom) {
nombre = nom;
edad = 0;
}
double area() {
return [Link] * radio * radio;
}
}
3.10 INTERFACES
Una interfaz define un contrato que las clases deben implementar. Todos los métodos de una
interfaz son públicos y abstractos por defecto.
Ejemplo:
interface Vehiculo {
void arrancar();
void frenar();
}
class Moto implements Vehiculo {
public void arrancar() {
[Link]("Moto arrancando");
}
public void frenar() {
[Link]("Moto frenando");
}
}
Ejemplo de super:
class Animal {
void hacerSonido() {
[Link]("Sonido genérico");
}
}
class Perro extends Animal {
void hacerSonido() {
[Link]();
[Link]("Guau");
}
}
3.12 ENUMERACIONES
Una enumeración es un tipo que define un conjunto fijo de constantes.
Ejemplo:
enum Dia {
LUNES, MARTES, MIERCOLES, JUEVES, VIERNES
}
public class Principal {
public static void main(String[] args) {
Dia d = [Link];
[Link]("Hoy es " + d);
}
}
CAPÍTULO 4: MANEJO DE CADENAS DE TEXTO EN JAVA
4.1 LA CLASE STRING
En Java, las cadenas de texto son representadas mediante la clase String, que forma parte del
paquete [Link]. Esta clase permite trabajar con secuencias de caracteres de forma sencilla, ya que
provee una gran cantidad de métodos útiles para manipular, comparar y transformar cadenas. Las
instancias de String son inmutables, lo que significa que una vez creada una cadena, su contenido
no puede cambiar. Cualquier operación que modifique una cadena en realidad devuelve una nueva
instancia de String.
Creación de cadenas:
String cadena1 = "Hola mundo";
String cadena2 = new String("Hola mundo");
Ambas formas son válidas, pero la primera es más eficiente porque utiliza el pool de cadenas que
Java mantiene internamente para optimizar el uso de memoria.
Longitud de una cadena:
int longitud = [Link]();
Acceso a un carácter específico:
char letra = [Link](0); // Devuelve 'H'
Subcadenas:
String sub = [Link](5); // Devuelve "mundo"
String sub2 = [Link](0, 4); // Devuelve "Hola"
4.2 MÉTODOS ÚTILES DE STRING
La clase String incluye una gran variedad de métodos para manipular y consultar cadenas. A
continuación, se describen algunos de los más comunes y útiles.
equals y equalsIgnoreCase:
Permiten comparar el contenido de dos cadenas.
String a = "Hola";
String b = "hola";
boolean igual = [Link](b); // false
boolean igualIgnorarMayusculas = [Link](b); // true
compareTo:
Compara dos cadenas lexicográficamente.
String a = "manzana";
String b = "naranja";
int resultado = [Link](b); // resultado negativo porque "manzana" va antes que "naranja"
contains:
Verifica si una cadena contiene una subcadena.
String texto = "Bienvenido al mundo Java";
boolean contiene = [Link]("Java"); // true
startsWith y endsWith:
Verifican si una cadena empieza o termina con otra.
boolean empieza = [Link]("Bienvenido"); // true
boolean termina = [Link]("Java"); // true
indexOf y lastIndexOf:
Devuelven la posición de una subcadena o carácter.
int posicion = [Link]("mundo"); // 15
int ultimaOcurrencia = [Link]("o"); // 20
toUpperCase y toLowerCase:
Transforman la cadena a mayúsculas o minúsculas.
String mayusculas = [Link]();
String minusculas = [Link]();
trim:
Elimina espacios en blanco al principio y al final.
String mensaje = " Hola ";
String limpio = [Link](); // "Hola"
replace:
Reemplaza caracteres o subcadenas.
String texto = "perro";
String reemplazado = [Link]("r", "l"); // "pelro"
split:
Divide la cadena en partes usando un delimitador.
String frase = "uno,dos,tres";
String[] partes = [Link](","); // ["uno", "dos", "tres"]
4.3 STRINGBUILDER Y STRINGBUFFER
La clase String es inmutable, por lo tanto, si se necesita modificar cadenas de forma frecuente y
eficiente, se recomienda utilizar StringBuilder o StringBuffer.
StringBuilder es una clase mutable que permite modificar el contenido de una cadena sin crear
nuevos objetos. StringBuffer ofrece lo mismo, pero es sincronizado, lo cual lo hace adecuado en
contextos con múltiples hilos.
Ejemplo de uso de StringBuilder:
StringBuilder sb = new StringBuilder();
[Link]("Hola");
[Link](" ");
[Link]("mundo");
String resultado = [Link](); // "Hola mundo"
Principales métodos de StringBuilder y StringBuffer:
• append(String s): añade una cadena al final
• insert(int offset, String s): inserta una cadena en la posición indicada
• delete(int start, int end): elimina los caracteres entre las posiciones start y end
• reverse(): invierte el contenido
• replace(int start, int end, String s): reemplaza una parte de la cadena
• toString(): convierte el objeto en un String
Ejemplo:
StringBuilder sb = new StringBuilder("Hola");
[Link](4, " mundo"); // "Hola mundo"
[Link](0, 5); // "mundo"
[Link](); // "odnum"
String resultado = [Link]();
Diferencias entre String, StringBuilder y StringBuffer:
• String: inmutable, menos eficiente para modificaciones repetidas.
• StringBuilder: mutable, no sincronizado, más rápido en entornos de un solo hilo.
• StringBuffer: mutable, sincronizado, más lento pero seguro en entornos multihilo.
4.4 COMPARACIÓN Y MANIPULACIÓN DE CADENAS
Comparación de cadenas:
Existen varias formas de comparar cadenas en Java, según lo que se desea comparar.
1. Comparación por contenido (equals y equalsIgnoreCase)
String a = "Java";
String b = "Java";
String c = new String("Java");
a == b; // true (porque ambos apuntan al mismo objeto del pool)
a == c; // false (son objetos diferentes)
[Link](c); // true (contenido igual)
2. Comparación lexicográfica (compareTo)
compareTo devuelve:
• 0 si las cadenas son iguales
• Un número negativo si la primera cadena es menor
• Un número positivo si la primera cadena es mayor
3. Uso de región:
Se puede comparar partes de una cadena con regionMatches.
String a = "Hola mundo";
boolean region = [Link](5, "mundo", 0, 5); // true
Manipulación avanzada:
1. Eliminación de espacios:
String texto = " ejemplo ";
String limpio = [Link](); // "ejemplo"
2. Reemplazo múltiple:
String texto = "casa azul azul";
texto = [Link]("azul", "roja"); // "casa roja roja"
3. Extracción de palabras:
String oracion = "Java es un lenguaje";
String[] palabras = [Link](" ");
for (String palabra : palabras) {
[Link](palabra);
}
4. Validación de cadenas:
String email = "usuario@[Link]";
boolean valido = [Link]("@") && [Link](".com");
5. Concatenación eficiente:
En lugar de usar + repetidamente, es más eficiente usar StringBuilder en bucles:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
[Link](i).append(" ");
}
String resultado = [Link]();
CONCLUSIÓN DEL CAPÍTULO
El manejo de cadenas de texto en Java es fundamental en cualquier tipo de aplicación. La clase
String proporciona una base sólida para representar texto, mientras que StringBuilder y
StringBuffer permiten optimizar el rendimiento cuando se requiere modificar cadenas
repetidamente. Entender y dominar los métodos de comparación y manipulación de cadenas permite
escribir código más limpio, eficiente y profesional.
Capítulo 5: Arreglos y Estructuras de Datos en Java
5.1 Arreglos unidimensionales
Un arreglo unidimensional en Java es una estructura de datos que almacena múltiples elementos del
mismo tipo en una secuencia contigua de memoria. Los arreglos se utilizan cuando se conoce de
antemano el número de elementos que se desean almacenar.
Declaración y creación de un arreglo:
int[] numeros; // Declaración
numeros = new int[5]; // Creación
Inicialización de valores:
numeros[0] = 10;
numeros[1] = 20;
numeros[2] = 30;
numeros[3] = 40;
numeros[4] = 50;
Acceso a elementos:
[Link](numeros[2]); // Muestra 30
Ventajas:
• Acceso rápido a los elementos mediante índices.
• Simplicidad.
Desventajas:
• Tamaño fijo una vez declarado.
• No permite eliminar o insertar elementos dinámicamente.
Acceso a elementos:
[Link](matriz[1][2]); // Muestra 7
Bucle for-each:
for (int numero : numeros) {
[Link](numero);
}
Este bucle es más limpio, pero no permite modificar los elementos directamente ni conocer su
índice.
5.4 Colecciones (List, Set, Map)
Las colecciones son estructuras de datos dinámicas proporcionadas por Java para almacenar,
manipular y recuperar grupos de objetos.
List: Una colección ordenada que puede contener elementos duplicados.
Set: Una colección que no permite duplicados.
Map: Una colección de pares clave-valor.
[Link]([Link](1)); // Banana
HashMap:
Estructura de pares clave-valor. No garantiza orden.
import [Link];
[Link]([Link]("Ana")); // 25
HashSet:
Colección que no permite duplicados y no garantiza orden.
import [Link];
[Link]([Link]()); // 2
TreeSet:
Colección sin duplicados que mantiene los elementos ordenados.
import [Link];
[Link](numeros); // [1, 3, 5]
3. Errores (Errors)
Son condiciones graves del sistema que generalmente no deberían ser capturadas por el
programa.
Ejemplos:
• OutOfMemoryError
• StackOverflowError
public class EjemploError {
public static void recursividadInfinita() {
recursividadInfinita(); // StackOverflowError
}
• El bloque finally se ejecuta siempre, ocurra o no una excepción. Se usa para liberar
recursos como archivos o conexiones.
Ejemplo con finally:
public class EjemploFinally {
public static void main(String[] args) {
try {
int resultado = 10 / 0;
} catch (ArithmeticException e) {
[Link]("No se puede dividir por cero.");
} finally {
[Link]("Este bloque siempre se ejecuta.");
}
}
}
Reglas importantes:
• Un método puede declarar múltiples excepciones separadas por comas.
• Si una excepción es comprobada, debe ser manejada o declarada con throws.
• throw se usa para lanzar excepciones manualmente; throws para declararlas en métodos.
}
FILEREADER y FILEWRITER:
• FileReader: clase para leer archivos de texto carácter a carácter.
• FileWriter: clase para escribir caracteres en archivos de texto.
Ejemplo combinado:
import [Link].*;
public class ArchivoTexto {
public static void main(String[] args) {
try {
FileWriter fw = new FileWriter("[Link]");
[Link]("Primera línea.\nSegunda línea.");
[Link]();
FileReader fr = new FileReader("[Link]");
int c;
while ((c = [Link]()) != -1) {
[Link]((char)c);
}
[Link]();
} catch (IOException e) {
[Link]();
}
}
}
7.4 SERIALIZACIÓN DE OBJETOS
La serialización es el proceso de convertir un objeto en una secuencia de bytes para poder guardarlo
en un archivo o transmitirlo. Java facilita esto usando las clases ObjectOutputStream y
ObjectInputStream.
REQUISITOS:
• La clase debe implementar la interfaz Serializable.
EJEMPLO DE SERIALIZACIÓN Y DESERIALIZACIÓN:
import [Link].*;
class Persona implements Serializable {
private static final long serialVersionUID = 1L;
String nombre;
int edad;
public Persona(String nombre, int edad) {
[Link] = nombre;
[Link] = edad;
}
}
public class SerializarObjeto {
public static void main(String[] args) {
Persona p1 = new Persona("Ana", 30);
// Serializar objeto
try {
FileOutputStream fileOut = new FileOutputStream("[Link]");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
[Link](p1);
[Link]();
[Link]();
[Link]("Objeto serializado correctamente.");
} catch (IOException i) {
[Link]();
}
// Deserializar objeto
try {
FileInputStream fileIn = new FileInputStream("[Link]");
ObjectInputStream in = new ObjectInputStream(fileIn);
Persona p2 = (Persona) [Link]();
[Link]();
[Link]();
}
NOTAS:
• serialVersionUID se usa para asegurar compatibilidad entre versiones de la clase.
• Todos los atributos también deben ser serializables o marcarse como transient.
CONCLUSIÓN
En este capítulo hemos aprendido a usar la clase Scanner para entrada estándar, a manipular
archivos mediante File, FileReader y FileWriter, y a serializar objetos con ObjectOutputStream.
Estas herramientas son esenciales para manejar datos persistentes y comunicar programas con el
usuario o con otros sistemas.
Capítulo 9: Clases utilitarias del API de Java
Java proporciona un conjunto de clases utilitarias en su API que permiten realizar operaciones
comunes de forma sencilla y eficiente. Estas clases abarcan operaciones matemáticas, manipulación
de fechas y tiempos, colecciones, y tareas programadas, entre otras. Este capítulo explora las clases
más representativas de estas utilidades.
9.1 Clases utilitarias: Math, Arrays, Objects, Collections
• Clase Math
La clase Math proporciona métodos estáticos para operaciones matemáticas como potencias, raíces,
redondeo, funciones trigonométricas y logarítmicas. Algunos métodos útiles:
[Link](x) devuelve el valor absoluto
[Link](a, b) devuelve a elevado a la potencia b
[Link](x) devuelve la raíz cuadrada
[Link](a, b) y [Link](a, b) comparan dos valores
[Link](x) redondea al entero más cercano
[Link]() devuelve un número aleatorio entre 0.0 y 1.0
Ejemplo:
double raiz = [Link](25); // 5.0
int maximo = [Link](10, 20); // 20
double aleatorio = [Link](); // valor entre 0.0 y 1.0
• Clase Arrays
La clase Arrays contiene métodos estáticos para trabajar con arreglos (arrays). Permite ordenarlos,
buscarlos, copiarlos y compararlos.
[Link](array) ordena un array
[Link](array, clave) busca un valor en un array ordenado
[Link](arr1, arr2) compara si dos arrays son iguales
[Link](array, valor) llena un array con un valor
[Link](array, longitud) copia un array
Ejemplo:
int[] numeros = {5, 3, 8};
[Link](numeros); // ahora: {3, 5, 8}
int pos = [Link](numeros, 5); // devuelve 1
• Clase Objects
La clase Objects proporciona métodos para trabajar con objetos y realizar comprobaciones de
nulidad y comparaciones seguras.
[Link](a, b) compara dos objetos incluso si alguno es null
[Link](obj) lanza NullPointerException si el objeto es null
[Link](...) calcula el hashCode de varios objetos
[Link](obj, "valor por defecto") convierte un objeto a String
Ejemplo:
String a = null;
String b = "hola";
boolean sonIguales = [Link](a, b); // false
• Clase Collections
La clase Collections contiene métodos estáticos para manipular colecciones como listas, conjuntos
y mapas.
[Link](lista) ordena una lista
[Link](lista) invierte una lista
[Link](lista) mezcla aleatoriamente una lista
[Link](lista), [Link](lista) obtienen el máximo y mínimo
[Link](lista, elemento) cuenta cuántas veces aparece un valor
[Link](lista) crea una lista inmutable
Ejemplo:
List lista = [Link](1, 2, 3, 4);
[Link](lista); // cambia el orden aleatoriamente
9.2 Date, LocalDate, LocalTime, LocalDateTime
• Clase Date ([Link])
Es una clase antigua que representa una fecha y hora. Hoy día se considera obsoleta en muchos
casos y ha sido reemplazada por las clases del paquete [Link].
Date fecha = new Date();
[Link](fecha); // fecha y hora actual
Se pueden usar métodos como getTime() o setTime() para manejar fechas en milisegundos, pero es
preferible usar LocalDateTime para nuevas aplicaciones.
• Clase LocalDate ([Link])
Representa una fecha sin hora. Útil para fechas de calendario como cumpleaños o eventos.
LocalDate hoy = [Link]();
LocalDate nacimiento = [Link](1990, 5, 12);
LocalDate mañana = [Link](1);
LocalDate añoPasado = [Link](1);
Métodos comunes:
getYear(), getMonth(), getDayOfMonth(), isLeapYear(), isBefore(), isAfter()
• Clase LocalTime ([Link])
Representa solo una hora sin fecha.
LocalTime ahora = [Link]();
LocalTime horaFija = [Link](14, 30);
LocalTime enUnaHora = [Link](1);
• Clase LocalDateTime ([Link])
Combina una fecha y una hora.
LocalDateTime fechaHora = [Link]();
LocalDateTime evento = [Link](2025, 12, 25, 20, 0);
LocalDateTime futuro = [Link](5).minusHours(2);
Métodos útiles:
getYear(), getMonth(), getDayOfWeek(), plusMinutes(), minusDays()
9.3 Formato de fechas y horas
Para mostrar o interpretar fechas con un formato personalizado se usa la clase DateTimeFormatter
del paquete [Link].
DateTimeFormatter formatter = [Link]("dd/MM/yyyy");
LocalDate fecha = [Link](2025, 7, 5);
String texto = [Link](formatter); // "05/07/2025"
También se puede analizar un texto para convertirlo en fecha:
String texto = "15-08-2024";
DateTimeFormatter formato = [Link]("dd-MM-yyyy");
LocalDate fechaConvertida = [Link](texto, formato);
Formatos comunes:
"yyyy-MM-dd" (ISO estándar)
"dd/MM/yyyy"
"HH:mm:ss"
"dd MMMM yyyy" (por ejemplo "05 julio 2025")
Para fechas y horas completas:
LocalDateTime ahora = [Link]();
DateTimeFormatter f = [Link]("dd-MM-yyyy HH:mm");
String salida = [Link](f); // por ejemplo "05-07-2025 14:30"
9.4 Temporizadores y tareas programadas
Java permite ejecutar tareas con retardo o repetición usando clases como Timer, TimerTask y
ScheduledExecutorService.
• Timer y TimerTask ([Link])
Timer timer = new Timer();
TimerTask tarea = new TimerTask() {
public void run() {
[Link]("Ejecutando tarea...");
}
};
[Link](tarea, 3000); // se ejecuta una vez después de 3 segundos
También puede ejecutarse de forma periódica:
[Link](tarea, 0, 5000); // cada 5 segundos
• ScheduledExecutorService ([Link])
Más moderno y robusto que Timer.
ScheduledExecutorService scheduler = [Link](1);
Runnable tarea = () -> [Link]("Tarea ejecutada");
[Link](tarea, 2, [Link]); // se ejecuta después de 2 segundos
También se puede repetir periódicamente:
[Link](tarea, 0, 10, [Link]);
Este método es preferido en aplicaciones concurrentes y multiusuario, ya que maneja mejor los
errores y excepciones.
10.3 Sincronización
Cuando varios hilos acceden a recursos compartidos (como variables, archivos o estructuras de
datos), es necesario garantizar que estos accesos se realicen de forma ordenada para evitar
resultados inconsistentes. Esto se logra mediante la sincronización.
Java proporciona la palabra clave synchronized para evitar que múltiples hilos accedan a una
sección crítica del código simultáneamente.
Ejemplo de método sincronizado:
class Contador {
private int cuenta = 0;
public synchronized void incrementar() {
cuenta++;
}
}
Otra opción es usar bloques sincronizados:
synchronized(objeto) {
// sección crítica
}
También existen herramientas avanzadas en el paquete [Link] como ReentrantLock,
que permite mayor control sobre la sincronización, incluyendo bloqueo condicional y desbloqueo
manual.
10.4 Ejecutores y Callable
El paquete [Link] proporciona una forma más flexible y moderna de gestionar hilos
mediante el uso de ejecutores (Executors). La interfaz ExecutorService permite gestionar un grupo
de hilos (thread pool), reutilizar hilos y evitar la creación manual de nuevos hilos.
Ejemplo básico con ExecutorService:
import [Link];
import [Link];
class Tarea implements Runnable {
public void run() {
[Link]("Tarea ejecutada por: " + [Link]().getName());
}
}
public class Principal {
public static void main(String[] args) {
ExecutorService executor = [Link](3);
for (int i = 0; i < 10; i++) {
[Link](new Tarea());
}
[Link]();
}
}
Callable es similar a Runnable pero puede retornar un resultado y lanzar excepciones. Se usa junto
con Future para obtener el resultado de una tarea asincrónica.
Ejemplo con Callable:
import [Link].*;
class MiCallable implements Callable {
public Integer call() throws Exception {
return 123;
}
}
public class Principal {
public static void main(String[] args) throws Exception {
ExecutorService executor = [Link]();
Future futuro = [Link](new MiCallable());
[Link]("Resultado: " + [Link]());
[Link]();
}
}
10.5 Problemas comunes: race conditions, deadlocks
1. Condiciones de carrera (Race Conditions):
Ocurren cuando dos o más hilos acceden a una variable compartida sin sincronización adecuada, y
al menos uno de los accesos es una escritura. Esto puede producir resultados impredecibles y
errores difíciles de depurar.
Ejemplo típico:
class Contador {
private int cuenta = 0;
public void incrementar() {
cuenta = cuenta + 1; // No es atómica
}
}
Si múltiples hilos llaman a incrementar() sin sincronización, el valor final puede no ser correcto.
Solución: usar métodos sincronizados o variables atómicas como AtomicInteger.
2. Deadlocks (bloqueos mutuos):
Ocurren cuando dos o más hilos esperan mutuamente por un recurso que el otro posee, provocando
un ciclo de espera infinita.
Ejemplo:
class Recurso {
public synchronized void usar(Recurso otro) {
[Link]("Usando recurso y esperando otro");
[Link]();
}
public synchronized void completar() {
[Link]("Completado");
}
}
public class Principal {
public static void main(String[] args) {
Recurso r1 = new Recurso();
Recurso r2 = new Recurso();
Thread t1 = new Thread(() -> [Link](r2));
Thread t2 = new Thread(() -> [Link](r1));
[Link]();
[Link]();
}
}
Ambos hilos quedan esperando indefinidamente porque cada uno tiene un recurso y necesita el otro.
Soluciones comunes para evitar deadlocks:
• Adquirir los recursos siempre en el mismo orden.
• Usar timeouts.
• Emplear estructuras de control de concurrencia avanzadas (Locks, semáforos, etc.).
Capítulo 11: Desarrollo de interfaces gráficas con Swing
11.1 Introducción a Swing
Swing es un conjunto de bibliotecas gráficas de Java que permite crear interfaces gráficas de
usuario (GUI) para aplicaciones de escritorio. Swing forma parte del paquete [Link] y es una
mejora del toolkit AWT (Abstract Window Toolkit), ofreciendo mayor flexibilidad y una apariencia
más moderna. Swing está completamente escrito en Java, lo que permite que las interfaces sean
multiplataforma.
Swing proporciona una gran variedad de componentes como botones, etiquetas, cuadros de texto,
listas, menús, tablas y mucho más. Además, se puede personalizar fácilmente el aspecto y
comportamiento de los componentes.
Ventajas de Swing:
• Independencia de plataforma.
• Amplio conjunto de componentes.
• Soporte para temas (Look and Feel).
• Capacidad de personalización.
• Uso de contenedores y layout managers para organizar los elementos visuales.
11.2 Ventanas, paneles, botones, etiquetas
La clase base para crear una ventana es JFrame. Es el contenedor principal en una aplicación Swing.
Otros contenedores comunes incluyen JPanel para agrupar componentes y facilitar su organización.
Ejemplo básico con JFrame, JButton y JLabel:
import [Link].*;
public class VentanaBasica {
public static void main(String[] args) {
JFrame ventana = new JFrame("Mi primera ventana");
[Link](300, 200);
[Link](JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
[Link](etiqueta);
[Link](boton);
[Link](panel);
[Link](true);
}
}
Componentes principales:
• JFrame: ventana principal.
• JPanel: panel para contener otros componentes.
• JLabel: muestra texto no editable.
• JButton: botón que puede generar acciones.
11.3 Campos de texto, áreas de texto, menús
Los campos de texto permiten al usuario introducir texto en una sola línea (JTextField) o en varias
líneas (JTextArea). Los menús permiten organizar acciones y comandos dentro de la interfaz.
Ejemplo con JTextField, JTextArea y JMenu:
import [Link].;
import [Link].;
public class InterfazTextoMenu {
public static void main(String[] args) {
JFrame frame = new JFrame("Texto y Menús");
[Link](400, 300);
[Link](JFrame.EXIT_ON_CLOSE);
JTextField campoTexto = new JTextField(20);
JTextArea areaTexto = new JTextArea(5, 20);
[Link](itemSalir);
[Link](menuArchivo);
[Link](barraMenu);
[Link](panel);
[Link](true);
}
}
Componentes adicionales:
• JTextField: entrada de texto en una sola línea.
• JTextArea: entrada de texto en varias líneas.
• JScrollPane: permite añadir barras de desplazamiento a componentes como JTextArea.
• JMenuBar, JMenu, JMenuItem: componentes para crear menús.
11.4 Layouts y organización de componentes
Swing proporciona varios "Layout Managers" para controlar la disposición de los componentes
dentro de un contenedor. Algunos de los más comunes son:
• FlowLayout: disposición en fila.
• BorderLayout: divide el contenedor en cinco áreas (NORTH, SOUTH, EAST, WEST,
CENTER).
• GridLayout: cuadrícula de celdas iguales.
• BoxLayout: disposición en una sola línea vertical u horizontal.
Ejemplo con diferentes layouts:
import [Link].;
import [Link].;
public class EjemploLayouts {
public static void main(String[] args) {
JFrame frame = new JFrame("Layouts");
[Link](400, 300);
[Link](JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
[Link](new BorderLayout());
[Link](panel);
[Link](true);
}
}
Usar el layout correcto ayuda a crear interfaces más organizadas y adaptables.
11.5 Eventos y manejo de acciones
La interacción del usuario con los componentes se maneja mediante eventos. Por ejemplo, hacer
clic en un botón genera un evento que puede ser capturado y procesado mediante un listener.
Para los botones, se utiliza ActionListener:
import [Link].;
import [Link].;
public class EventoBoton {
public static void main(String[] args) {
JFrame frame = new JFrame("Eventos");
JButton boton = new JButton("Haz clic");
[Link](new ActionListener() {
public void actionPerformed(ActionEvent e) {
[Link](null, "¡Botón pulsado!");
}
});
[Link](boton);
[Link](200, 100);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
Otros tipos de eventos comunes:
• MouseListener: eventos del ratón.
• KeyListener: eventos del teclado.
• WindowListener: eventos de la ventana (abrir, cerrar, minimizar).
Se pueden implementar usando clases anónimas, expresiones lambda (desde Java 8) o clases
internas.
11.6 Tablas y listas
Swing ofrece componentes para mostrar y gestionar datos tabulares o listas de elementos. Las clases
principales son JTable y JList.
Ejemplo de JList:
import [Link].*;
public class ListaEjemplo {
public static void main(String[] args) {
JFrame frame = new JFrame("Lista");
String[] elementos = {"Elemento 1", "Elemento 2", "Elemento 3"};
JList lista = new JList<>(elementos);
JScrollPane scroll = new JScrollPane(lista);
[Link](scroll);
[Link](200, 150);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
Ejemplo de JTable:
import [Link].*;
public class TablaEjemplo {
public static void main(String[] args) {
JFrame frame = new JFrame("Tabla");
String[] columnas = {"Nombre", "Edad", "Ciudad"};
String[][] datos = {
{"Ana", "25", "Madrid"},
{"Luis", "30", "Barcelona"},
{"Elena", "22", "Valencia"}
};
[Link](scroll);
[Link](300, 150);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
Resumen de componentes:
• JList: lista de elementos seleccionables.
• JTable: tabla con filas y columnas.
• JScrollPane: permite añadir scroll a listas y tablas.
Capítulo 12: Acceso a bases de datos con JDBC
12.1 Introducción a JDBC
JDBC (Java Database Connectivity) es una API de Java que permite a las aplicaciones Java
conectarse y operar con bases de datos relacionales. JDBC proporciona un conjunto estándar de
interfaces y clases para enviar instrucciones SQL, obtener resultados y manejar errores de bases de
datos. Funciona como una capa intermedia entre una aplicación Java y una base de datos, haciendo
posible la independencia del motor de base de datos al usar diferentes drivers.
Componentes clave de JDBC:
• DriverManager: Gestiona una lista de drivers de base de datos.
• Connection: Representa una conexión con una base de datos.
• Statement: Permite ejecutar consultas SQL simples.
• PreparedStatement: Ejecuta consultas SQL parametrizadas.
• ResultSet: Contiene los datos devueltos por una consulta.
• SQLException: Maneja los errores que se produzcan durante la operación con la base de
datos.
12.2 Conexión con bases de datos
Para conectarse a una base de datos usando JDBC, se necesitan tres cosas: el driver JDBC
correspondiente, la URL de la base de datos, y las credenciales de acceso.
Pasos para establecer la conexión:
1. Cargar el driver JDBC.
2. Crear la conexión mediante la clase DriverManager.
3. Gestionar excepciones con SQLException.
Ejemplo:
import [Link];
import [Link];
import [Link];
public class ConexionBD {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/empresa";
String usuario = "root";
String contrasena = "password";
try {
Connection conexion = [Link](url, usuario,
contrasena);
[Link]("Conexión exitosa");
[Link]();
} catch (SQLException e) {
[Link]("Error al conectar: " + [Link]());
}
}
}
Nota: En versiones modernas de Java, no es necesario registrar el driver manualmente si está
incluido en el classpath.
12.3 Sentencias SQL desde Java
Una vez establecida la conexión, se pueden ejecutar sentencias SQL usando las interfaces Statement
o PreparedStatement.
El método executeQuery() se usa para sentencias SELECT, y el método executeUpdate() para
INSERT, UPDATE y DELETE.
Ejemplo de SELECT:
import [Link].*;
public class ConsultarEmpleados {
public static void main(String[] args) {
try {
Connection conexion = [Link]("jdbc:mysql://localhost:3306/empresa",
"root", "password");
Statement stmt = [Link]();
ResultSet rs = [Link]("SELECT * FROM empleados");
while ([Link]()) {
int id = [Link]("id");
String nombre = [Link]("nombre");
[Link]("ID: " + id + ", Nombre: " + nombre);
}
[Link]();
[Link]();
[Link]();
} catch (SQLException e) {
[Link]("Error: " + [Link]());
}
}
}
12.4 PreparedStatement y ResultSet
PreparedStatement permite ejecutar sentencias SQL con parámetros, aumentando la seguridad
(prevención de SQL Injection) y el rendimiento.
Ejemplo de uso de PreparedStatement:
import [Link].*;
public class BuscarEmpleado {
public static void main(String[] args) {
try {
Connection conexion = [Link]("jdbc:mysql://localhost:3306/empresa",
"root", "password");
String sql = "SELECT * FROM empleados WHERE id = ?";
PreparedStatement pstmt = [Link](sql);
[Link](1, 1);
ResultSet rs = [Link]();
if ([Link]()) {
[Link]("Nombre: " + [Link]("nombre"));
}
[Link]();
[Link]();
[Link]();
} catch (SQLException e) {
[Link]("Error: " + [Link]());
}
}
}
El objeto ResultSet proporciona métodos para acceder a los datos obtenidos como getInt(),
getString(), getDouble(), etc.
12.5 Inserción, actualización y eliminación
Para realizar operaciones de modificación sobre la base de datos (INSERT, UPDATE, DELETE), se
usa executeUpdate() que retorna el número de filas afectadas.
Ejemplo de inserción:
import [Link].*;
public class InsertarEmpleado {
public static void main(String[] args) {
try {
Connection conexion = [Link]("jdbc:mysql://localhost:3306/empresa",
"root", "password");
String sql = "INSERT INTO empleados (nombre, salario) VALUES (?, ?)";
PreparedStatement pstmt = [Link](sql);
[Link](1, "Laura");
[Link](2, 35000);
int filas = [Link]();
[Link]("Filas insertadas: " + filas);
[Link]();
[Link]();
} catch (SQLException e) {
[Link]("Error: " + [Link]());
}
}
}
Ejemplo de actualización:
String sql = "UPDATE empleados SET salario = ? WHERE id = ?";
PreparedStatement pstmt = [Link](sql);
[Link](1, 40000);
[Link](2, 1);
[Link]();
Ejemplo de eliminación:
String sql = "DELETE FROM empleados WHERE id = ?";
PreparedStatement pstmt = [Link](sql);
[Link](1, 2);
[Link]();
12.6 Manejo de transacciones
Por defecto, JDBC realiza auto-commit después de cada sentencia. Para realizar transacciones
manuales se puede desactivar el auto-commit.
Ejemplo de transacción:
import [Link].*;
public class TransaccionEjemplo {
public static void main(String[] args) {
try {
Connection conexion = [Link]("jdbc:mysql://localhost:3306/empresa",
"root", "password");
[Link](false);
PreparedStatement pstmt1 = [Link]("UPDATE empleados
SET salario = salario + 1000 WHERE id = ?");
[Link](1, 1);
[Link]();
[Link]();
[Link]("Transacción completada con éxito");
[Link]();
[Link]();
[Link]();
} catch (SQLException e) {
[Link]("Error en la transacción: " + [Link]());
try {
[Link]();
[Link]("Transacción revertida");
} catch (SQLException ex) {
[Link]("Error al hacer rollback: " + [Link]());
}
}
}
}
12.7 Cierre y gestión de recursos
Es fundamental cerrar todos los recursos JDBC (ResultSet, Statement, Connection) una vez que han
sido usados, para liberar recursos del sistema y evitar fugas de memoria.
Desde Java 7 se recomienda usar try-with-resources, que cierra automáticamente los objetos que
implementan AutoCloseable.
Ejemplo con try-with-resources:
import [Link].*;
public class ConsultaConTry {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/empresa";
String user = "root";
String password = "password";
String sql = "SELECT * FROM empleados";
try (
Connection conexion = [Link](url, user, password);
Statement stmt = [Link]();
ResultSet rs = [Link](sql);
) {
while ([Link]()) {
[Link]("Empleado: " + [Link]("nombre"));
}
} catch (SQLException e) {
[Link]("Error: " + [Link]());
}
}
}
Resumen:
• JDBC es la API estándar de Java para trabajar con bases de datos relacionales.
• Se puede conectar a cualquier base de datos siempre que se tenga el driver adecuado.
• Statement y PreparedStatement permiten ejecutar sentencias SQL.
• ResultSet permite recorrer los resultados de las consultas.
• PreparedStatement mejora la seguridad y eficiencia.
• Las transacciones permiten ejecutar múltiples operaciones como una unidad lógica.
• El cierre adecuado de recursos es esencial para evitar problemas de rendimiento.
Este capítulo proporciona una base completa para interactuar con bases de datos usando JDBC. En
siguientes capítulos se puede profundizar en conexión con pool de conexiones, ORMs como
Hibernate o JPA, y acceso a bases de datos no relacionales.
Capítulo 13: Programación web con Java (introducción)
13.1 Java EE y Java Jakarta
Java EE (Java Platform, Enterprise Edition), actualmente conocido como Jakarta EE tras su
transferencia a la Eclipse Foundation, es una plataforma robusta y estandarizada para el desarrollo
de aplicaciones empresariales y web en Java. Jakarta EE ofrece un conjunto de especificaciones que
extienden Java SE para facilitar la creación de aplicaciones distribuidas, transaccionales y
escalables. Estas especificaciones incluyen tecnologías como Servlets, JSP (JavaServer Pages), JSF
(JavaServer Faces), JPA (Java Persistence API), EJB (Enterprise JavaBeans) y muchas más.
Jakarta EE proporciona una arquitectura basada en componentes reutilizables y contenedores de
servidor que gestionan servicios como la seguridad, el ciclo de vida de los objetos, la persistencia y
la concurrencia. Uno de los beneficios principales es que el desarrollador puede enfocarse en la
lógica de negocio sin preocuparse por los detalles de bajo nivel del servidor.
Los servidores de aplicaciones como GlassFish, WildFly o Payara implementan estas
especificaciones y permiten desplegar aplicaciones web empresariales de forma sencilla.
13.2 Servlets y JSP
Los Servlets son componentes Java que se ejecutan en un servidor web o de aplicaciones. Actúan
como controladores que procesan solicitudes HTTP y generan respuestas, típicamente en HTML.
Un Servlet es una clase Java que extiende la clase HttpServlet e implementa métodos como doGet y
doPost para manejar solicitudes GET y POST respectivamente.
JSP (JavaServer Pages) es una tecnología que permite insertar código Java directamente dentro de
páginas HTML usando una sintaxis especial con etiquetas como <% ... %>. Esto facilita la
generación dinámica de contenido HTML, ya que el código Java se traduce en un Servlet en tiempo
de ejecución.
Los Servlets y JSP trabajan juntos en una arquitectura típica MVC (Modelo Vista Controlador),
donde el Servlet actúa como el controlador que gestiona la lógica y la navegación, y las JSP como
vistas que presentan la información al usuario.
Ejemplo básico de Servlet:
import [Link].;
import [Link].;
import [Link].*;
public class HolaMundoServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
[Link]("text/html");
PrintWriter out = [Link]();
[Link]("");
[Link]("Hola Mundo desde Servlet");
[Link]("");
}
}
13.3 Configuración de un servidor Tomcat
Apache Tomcat es uno de los servidores de aplicaciones más populares para ejecutar Servlets y JSP.
Para configurar Tomcat y empezar a trabajar con Java web, se siguen los siguientes pasos:
1. Descargar Tomcat desde el sitio oficial de Apache Tomcat.
2. Descomprimir el archivo en una carpeta de tu sistema.
3. Establecer la variable de entorno JAVA_HOME apuntando al JDK instalado.
4. Ejecutar el servidor con el script [Link] (Windows) o [Link] (Linux/Mac).
5. Acceder a la consola administrativa en [Link]
Para desplegar una aplicación web en Tomcat, se debe:
• Crear una estructura de proyecto que incluya un archivo [Link] dentro de la carpeta WEB-
INF
• Incluir las clases compiladas en la carpeta WEB-INF/classes
• Empaquetar todo en un archivo WAR y copiarlo a la carpeta webapps de Tomcat
Ejemplo de estructura básica:
miapp/
├── [Link]
└── WEB-INF/
├── [Link]
└── classes/
└── [Link]
El archivo [Link] configura el mapeo del Servlet:
13.4 Formularios HTML y envío a Servlets
Una funcionalidad común en aplicaciones web es capturar datos del usuario mediante formularios
HTML y enviarlos al servidor para ser procesados. Esto se hace mediante la etiqueta especificando
el método (GET o POST) y la URL de destino que será manejada por un Servlet.
Ejemplo de formulario HTML:
Este formulario enviará el valor del campo "nombre" al Servlet mapeado en la URL "/procesar". El
Servlet debe implementar el método doPost para capturar y procesar los datos.
Ejemplo de Servlet que recibe datos del formulario:
public class ProcesarFormulario extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
String nombre = [Link]("nombre");
[Link]("text/html");
PrintWriter out = [Link]();
[Link]("");
[Link]("Bienvenido " + nombre + "");
[Link]("");
}
}
13.5 Conexión de Servlets a bases de datos
Para que un Servlet interactúe con una base de datos, se utiliza JDBC (Java Database Connectivity).
Esto permite establecer conexiones, ejecutar consultas SQL y procesar resultados desde Java.
Los pasos básicos son:
1. Cargar el driver JDBC adecuado
2. Establecer la conexión con la base de datos
3. Crear y ejecutar consultas
4. Procesar los resultados
5. Cerrar la conexión
Ejemplo de conexión de un Servlet a una base de datos MySQL:
import [Link].;
import [Link].;
import [Link].;
import [Link].;
public class ConsultaUsuario extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
String usuario = [Link]("usuario");
String clave = [Link]("clave");
[Link]("text/html");
PrintWriter out = [Link]();
try {
[Link]("[Link]");
Connection con =
[Link]("jdbc:mysql://localhost:3306/miBD", "root",
"password");
if ([Link]()) {
[Link]("<h2>Acceso concedido</h2>");
} else {
[Link]("<h2>Acceso denegado</h2>");
}
[Link]();
} catch (Exception e) {
[Link]("Error: " + [Link]());
}
}
}
Es importante cerrar siempre las conexiones para liberar recursos y evitar problemas de
rendimiento.
Capítulo 14: Introducción a Spring Framework
Spring Framework es una de las plataformas más populares para el desarrollo de aplicaciones Java
modernas, especialmente en el contexto de aplicaciones empresariales y web. Su diseño modular
permite trabajar de manera eficiente con componentes como la inversión de control (IoC), la
inyección de dependencias, la arquitectura MVC, y la persistencia de datos con JPA. En este
capítulo exploraremos los conceptos esenciales de Spring, con un enfoque práctico y progresivo.
14.1 Inversión de control (IoC) y contenedores
Uno de los conceptos centrales de Spring es la Inversión de Control (IoC), también conocida como
Inyección de Dependencias (DI). En lugar de que una clase cree sus propias dependencias, un
contenedor de Spring las crea y las inyecta. Esto permite un código más flexible, desacoplado y
fácil de testear.
El contenedor de Spring es el responsable de instanciar, configurar y ensamblar los objetos de la
aplicación. Este contenedor se configura mediante archivos XML, anotaciones o clases Java. Los
objetos gestionados por el contenedor se denominan beans.
Ejemplo básico de un bean:
public class ServicioSaludo {
public void saludar() {
[Link]("Hola desde Spring!");
}
}
Configuración con anotación:
@Component
public class ServicioSaludo {
public void saludar() {
[Link]("Hola desde Spring!");
}
}
Para que Spring detecte esta clase, se debe escanear el paquete mediante anotaciones como
@ComponentScan.
14.2 Spring Boot y creación de proyectos
Spring Boot simplifica el desarrollo de aplicaciones Spring mediante configuración automática y un
entorno de ejecución preconfigurado. Permite crear aplicaciones listas para producción con mínima
configuración.
Para crear un proyecto Spring Boot se puede utilizar Spring Initializr ([Link] Basta
con seleccionar los siguientes parámetros:
• Lenguaje: Java
• Versión: 3.x (o la más reciente)
• Dependencias: Spring Web, Spring Data JPA, H2 Database (u otra base de datos), Spring
Boot DevTools
Spring Boot proporciona un archivo principal con la clase con anotación @SpringBootApplication:
@SpringBootApplication
public class AplicacionPrincipal {
public static void main(String[] args) {
[Link]([Link], args);
}
}
Esta anotación engloba otras tres: @Configuration, @EnableAutoConfiguration y
@ComponentScan.
14.3 Inyección de dependencias
Spring permite inyectar dependencias de varias formas: mediante constructor, métodos setter o
directamente con anotaciones. Las anotaciones más comunes son @Autowired, @Component,
@Service y @Repository.
Ejemplo con inyección por constructor:
@Component
public class ClienteServicio {
private final ServicioSaludo servicioSaludo;
@Autowired
public ClienteServicio(ServicioSaludo servicioSaludo) {
[Link] = servicioSaludo;
}
}
Spring detectará automáticamente el bean ServicioSaludo y lo inyectará en ClienteServicio.
Es posible usar perfiles (@Profile), ámbitos (@Scope) y cualificadores (@Qualifier) para controlar
más finamente cómo se inyectan las dependencias.
14.4 Repositorios y controladores REST
Spring facilita la creación de APIs RESTful a través del módulo Spring Web. Los controladores
REST se definen usando @RestController y @RequestMapping o @GetMapping, @PostMapping,
etc.
Ejemplo de controlador REST:
@RestController
@RequestMapping("/saludos")
public class SaludoController {
@GetMapping
public String saludar() {
return "Hola mundo desde Spring REST!";
}
}
Para manejar la capa de persistencia, se utilizan interfaces que extienden JpaRepository, las cuales
son detectadas automáticamente gracias a la anotación @Repository.
Ejemplo:
@Entity
public class Usuario {
@Id
@GeneratedValue
private Long id;
private String nombre;
}
public interface UsuarioRepository extends JpaRepository<Usuario, Long> {
List findByNombre(String nombre);
}
Los métodos personalizados se construyen siguiendo una convención de nombres, y Spring
implementa automáticamente las consultas.
14.5 JPA y conexión a base de datos
Spring Data JPA es un módulo que permite trabajar con bases de datos relacionales usando JPA
(Java Persistence API). Spring se integra con proveedores como Hibernate para realizar el mapeo
objeto-relacional (ORM).
La configuración de la base de datos puede realizarse en el archivo [Link]:
[Link]=jdbc:h2:mem:testdb
[Link]=[Link]
[Link]=sa
[Link]=
[Link]-auto=update
Con esta configuración, Spring Boot crea una base de datos H2 en memoria. También se puede usar
MySQL, PostgreSQL u otra base de datos.
La entidad se define con @Entity, y los campos se anotan con @Id, @GeneratedValue, @Column,
etc.
Ejemplo:
@Entity
public class Producto {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
private String nombre;
private double precio;
}
Los repositorios se usan para acceder a los datos sin escribir código SQL:
public interface ProductoRepository extends JpaRepository<Producto, Long> {
List findByNombreContaining(String texto);
}
14.6 Arquitectura MVC en Spring
Spring MVC es un modelo de desarrollo basado en la arquitectura Modelo-Vista-Controlador. Esta
arquitectura separa la lógica de negocio, la lógica de presentación y el control del flujo de la
aplicación.
Modelo: Representa los datos y reglas de negocio (entidades, servicios).
Vista: Interfaz de usuario (Thymeleaf, JSP, HTML).
Controlador: Gestiona las peticiones y coordina la vista y el modelo.
Ejemplo de controlador MVC:
@Controller
public class ProductoControlador {
@Autowired
private ProductoRepository productoRepository;
@GetMapping("/productos")
public String listarProductos(Model model) {
[Link]("productos", [Link]());
return "productos"; // plantilla [Link]
}
}
El archivo HTML correspondiente puede utilizar el motor de plantillas Thymeleaf para mostrar los
datos:
Spring MVC maneja automáticamente la conversión de datos, validaciones, gestión de sesiones y
otros aspectos del desarrollo web moderno.
Conclusión
Spring Framework, junto con Spring Boot, ofrece un ecosistema completo para desarrollar
aplicaciones Java modernas, modulares y mantenibles. Desde la inversión de control, pasando por la
inyección de dependencias, hasta la creación de APIs REST y la persistencia con JPA, Spring
permite construir aplicaciones robustas y escalables con poco código repetitivo. Comprender su
arquitectura MVC facilita aún más el desarrollo de aplicaciones web limpias y bien estructuradas.
Capítulo 15: Pruebas y depuración en Java
15.1 Introducción a JUnit
JUnit es un framework para realizar pruebas unitarias en Java. Las pruebas unitarias consisten en
verificar que unidades pequeñas de código, generalmente métodos, funcionan correctamente de
manera aislada. JUnit proporciona anotaciones y métodos para definir y ejecutar pruebas de forma
automatizada, facilitando la identificación de errores durante el desarrollo.
Para usar JUnit, se debe incluir la dependencia correspondiente en el proyecto. Por ejemplo, usando
Maven:
<dependency>
<groupId>[Link]</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
La versión más usada actualmente es JUnit 5, también conocida como Jupiter. Ofrece una API
moderna, soporte para pruebas parametrizadas y mejor integración con IDEs y herramientas de
construcción.
Una clase de prueba típica en JUnit 5 contiene métodos anotados con @Test que definen las
pruebas. Por ejemplo:
import [Link];
import static [Link].*;
class CalculadoraTest {
@Test
void sumaDosNumeros() {
Calculadora calc = new Calculadora();
int resultado = [Link](2, 3);
assertEquals(5, resultado);
}
}
Las pruebas unitarias deben ser independientes, repetibles y rápidas. Es importante cubrir tanto
casos normales como casos límite o excepcionales para asegurar la robustez del código.
15.3 Mocking con Mockito
Mockito es un framework para crear objetos simulados (mocks) en las pruebas unitarias. Los mocks
permiten aislar la unidad bajo prueba simulando dependencias externas, como bases de datos,
servicios web o componentes complejos.
Para usar Mockito, también se añade como dependencia:
<dependency>
<groupId>[Link]</groupId>
<artifactId>mockito-core</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
class ServicioUsuarioTest {
@Test
void obtenerUsuarioPorId() {
RepositorioUsuario repoMock = mock([Link]);
Usuario usuarioSimulado = new Usuario(1, "Ana");
when([Link](1)).thenReturn(usuarioSimulado);
assertEquals("Ana", [Link]());
verify(repoMock).buscarPorId(1);
}
}
Ejemplo:
/**
* Calcula la suma de dos enteros.
*
* @param a El primer número entero.
* @param b El segundo número entero.
* @return La suma de a y b.
*/
public int sumar(int a, int b) {
return a + b;
}
private Singleton() {
// Constructor privado evita instanciación externa
}
• Factory (Fábrica):
El patrón Factory define una interfaz para crear objetos, pero permite a las subclases decidir qué
clase instanciar. Se usa para encapsular la creación de objetos, evitando dependencia directa con
clases concretas.
Ejemplo:
public interface Animal {
void hacerSonido();
}
• Observer (Observador):
El patrón Observer define una dependencia uno a muchos entre objetos, de modo que cuando uno
cambia su estado, todos sus dependientes son notificados y actualizados automáticamente. Se usa en
sistemas de eventos o interfaces gráficas.
Ejemplo básico:
import [Link];
import [Link];
interface Observador {
void actualizar(String mensaje);
}
class Sujeto {
private List<Observador> observadores = new ArrayList<>();
• MVC (Modelo-Vista-Controlador):
MVC es un patrón arquitectónico que separa la aplicación en tres componentes:
• Modelo: Gestiona los datos y la lógica de negocio.
• Vista: Presenta los datos al usuario.
• Controlador: Recibe las acciones del usuario y coordina el modelo y la vista.
Esta separación mejora la modularidad y facilita el mantenimiento y pruebas.
Ejemplo simplificado:
// Modelo
public class Modelo {
private String dato;
// Vista
public class Vista {
public void mostrarDato(String dato) {
[Link]("Dato: " + dato);
}
}
// Controlador
public class Controlador {
private Modelo modelo;
private Vista vista;
Para concluir, adoptar buenas prácticas y patrones de diseño en Java es fundamental para crear
software limpio, eficiente y fácil de mantener. El conocimiento y aplicación de principios como
SOLID, junto con la refactorización continua y documentación clara, sumado al uso adecuado de
patrones como Singleton, Factory, Observer y MVC, aporta calidad y profesionalismo a los
proyectos.
Capítulo 17: Herramientas y entornos de desarrollo en Java
17.1 Uso de IDEs: IntelliJ IDEA, Eclipse, NetBeans
En el desarrollo moderno de aplicaciones Java, los entornos de desarrollo integrados (IDEs) son
fundamentales para mejorar la productividad, la organización y la depuración del código. Los tres
IDEs más populares para Java son IntelliJ IDEA, Eclipse y NetBeans.
IntelliJ IDEA es un IDE desarrollado por JetBrains, conocido por su potente asistencia de código,
refactorización avanzada, integración con sistemas de control de versiones y herramientas de
construcción, así como soporte para múltiples frameworks y tecnologías. Su versión Community es
gratuita y suficiente para muchos proyectos, mientras que la versión Ultimate ofrece
funcionalidades avanzadas para desarrollo empresarial.
Eclipse es uno de los IDEs más antiguos y populares para Java. Es open source y cuenta con un
ecosistema extenso de plugins que permiten ampliar sus funcionalidades para diferentes lenguajes y
frameworks. Eclipse es muy usado en proyectos grandes y en ambientes corporativos por su
flexibilidad.
NetBeans es un IDE también open source, patrocinado inicialmente por Sun Microsystems y luego
por Apache. Tiene integración nativa con Maven y Gradle, y facilita la creación rápida de proyectos
Java con plantillas y asistentes. Es muy amigable para principiantes y ofrece soporte para desarrollo
web, móvil y de escritorio.
En general, estos IDEs permiten editar código con resaltado sintáctico, autocompletado, navegación
rápida, integración con sistemas de control de versiones, ejecución y depuración de aplicaciones,
gestión de dependencias y pruebas unitarias.
17.2 Uso de Git y GitHub
Git es un sistema de control de versiones distribuido que permite gestionar el historial de cambios
en el código fuente. Es fundamental para trabajar en equipo, ya que permite que múltiples
desarrolladores colaboren sin perder versiones anteriores ni sobrescribir el trabajo de otros.
GitHub es una plataforma web que aloja repositorios Git y facilita la colaboración mediante
funcionalidades como issues, pull requests, revisiones de código, wikis y gestión de proyectos.
En un proyecto Java, se recomienda inicializar un repositorio Git desde el inicio. Se pueden realizar
commits frecuentes con mensajes descriptivos para documentar los cambios. Para subir el código a
GitHub, se crea un repositorio remoto y se conecta al local mediante comandos git remote add.
Luego, se usa git push para subir los commits.
Git permite crear ramas (branches) para trabajar en nuevas funcionalidades o correcciones sin
afectar la rama principal. Al terminar, se pueden fusionar con merge o rebase. Es importante
resolver conflictos de código cuando dos ramas modifican las mismas líneas.
Los IDEs como IntelliJ IDEA, Eclipse y NetBeans ofrecen integración con Git y GitHub, lo que
facilita operaciones como commit, push, pull y merge desde la interfaz gráfica sin usar la consola.
17.3 Automatización con Maven y Gradle
Maven y Gradle son herramientas de automatización de construcción que gestionan la compilación,
ejecución de pruebas, generación de documentación, empaquetado y manejo de dependencias en
proyectos Java.
Maven utiliza un archivo de configuración llamado [Link] donde se declaran las dependencias,
plugins y configuraciones del proyecto. Su estructura basada en convenciones facilita la
estandarización y portabilidad entre proyectos. Al ejecutar comandos como mvn clean install,
Maven descarga dependencias del repositorio central, compila el código, ejecuta pruebas y genera
artefactos empaquetados.
Gradle es una herramienta más moderna y flexible que usa scripts en Groovy o Kotlin DSL. Permite
configuraciones dinámicas y mejores tiempos de construcción gracias a su sistema de cacheo y
construcción incremental. Su archivo [Link] declara las dependencias y tareas. Gradle es
especialmente popular en proyectos Android, pero también en aplicaciones Java de servidor y
escritorio.
Ambas herramientas permiten definir tareas personalizadas, gestionar proyectos multi-módulo, y
ejecutar fases específicas como pruebas unitarias, análisis estático, generación de informes y
despliegue.
17.4 Construcción de proyectos modulares
Con Java 9 se introdujo el sistema de módulos, que permite dividir grandes aplicaciones en módulos
independientes y encapsulados. Esto mejora la organización, reutilización y seguridad del código.
Un módulo Java se define con un archivo [Link] donde se declara el nombre del módulo,
los paquetes que exporta y las dependencias con otros módulos. Por ejemplo:
module [Link] {
requires [Link];
exports [Link];
}
La construcción modular facilita la carga dinámica de módulos, evita conflictos de versiones y
reduce el tamaño final de las aplicaciones.
Maven y Gradle soportan proyectos modulares. En Maven, se pueden configurar múltiples módulos
en un proyecto padre con un archivo [Link] principal y varios [Link] en subdirectorios. Gradle
permite definir subproyectos y sus dependencias mediante configuraciones en [Link] y
[Link].
17.5 Integración continua
La integración continua (CI) es una práctica de desarrollo donde los cambios en el código se
integran de forma frecuente y automática, permitiendo detectar errores rápidamente y asegurar la
calidad.
Para proyectos Java, se configuran pipelines de CI que ejecutan automáticamente compilaciones,
pruebas unitarias, análisis estático de código, empaquetado y despliegue a entornos de prueba cada
vez que se hace un commit o push al repositorio.
Herramientas populares de CI incluyen Jenkins, GitHub Actions, GitLab CI/CD, Travis CI y
CircleCI. Estas herramientas se configuran con scripts o archivos YAML que definen las etapas,
comandos y condiciones del pipeline.
Un pipeline básico de CI para un proyecto Java con Maven podría incluir:
• Checkout del código desde GitHub
• Instalación de Java y Maven en el agente
• Ejecución de mvn clean test para compilar y ejecutar pruebas
• Análisis de resultados y notificación a desarrolladores
La CI mejora la colaboración, reduce defectos y acelera el ciclo de desarrollo.
Resumen
Este capítulo presentó las principales herramientas y entornos para el desarrollo en Java, incluyendo
IDEs potentes como IntelliJ IDEA, Eclipse y NetBeans, el control de versiones con Git y GitHub, la
automatización con Maven y Gradle, la construcción modular con Java 9 y posteriores, y las
prácticas de integración continua para asegurar calidad y eficiencia. Estas herramientas y prácticas
son esenciales para el desarrollo profesional y colaborativo de proyectos Java modernos.
Capítulo 18: Proyecto Final en Java
18.1 Diseño y planificación del proyecto
El primer paso para la realización de un proyecto en Java es su diseño y planificación. Esta fase es
fundamental para definir el alcance, los objetivos, las funcionalidades y las restricciones del
sistema. Para ello se recomienda:
• Definir el problema a resolver y los requisitos funcionales y no funcionales.
• Analizar el entorno donde se desplegará la aplicación.
• Realizar un diseño arquitectónico inicial que incluya diagramas UML como diagramas de
clases, de casos de uso y de secuencia.
• Planificar las tareas, asignar tiempos estimados y definir las fases de desarrollo.
• Seleccionar las herramientas, frameworks y librerías que se usarán.
Un buen diseño ayuda a evitar problemas durante el desarrollo y facilita la integración de módulos y
futuras ampliaciones.
18.2 Desarrollo en fases (modelo incremental)
El desarrollo incremental consiste en construir el proyecto por etapas o fases, donde en cada fase se
añade funcionalidad hasta completar el sistema. Este modelo permite:
• Entregar versiones funcionales parciales para pruebas tempranas.
• Detectar errores o desviaciones de requisitos antes de completar el proyecto.
• Adaptar el diseño según el feedback recibido.
Para aplicar este modelo en Java:
• Dividir el proyecto en módulos o funcionalidades independientes.
• Implementar primero las funciones básicas y críticas.
• Probar y validar cada incremento antes de continuar.
• Añadir mejoras y funcionalidades secundarias en incrementos sucesivos.
Por ejemplo, en un sistema de gestión, el primer incremento puede incluir el registro de usuarios y
autenticación, el segundo la gestión de datos básicos y el tercero funcionalidades avanzadas como
reportes o gráficos.
18.3 Pruebas y validación del sistema
Las pruebas son esenciales para garantizar que el sistema funciona correctamente, cumple con los
requisitos y es estable. En Java existen varias estrategias:
• Pruebas unitarias: prueban métodos o clases individuales. Se recomienda usar frameworks
como JUnit para automatizarlas.
• Pruebas de integración: verifican que los módulos funcionan bien en conjunto.
• Pruebas funcionales: comprueban que el sistema cumple con los requisitos desde la
perspectiva del usuario.
• Pruebas de aceptación: realizadas por usuarios finales o clientes para validar el producto.
Se deben definir casos de prueba con entradas esperadas y resultados esperados. Además es
importante realizar pruebas de rendimiento y manejo de errores. La validación asegura que el
software cumple las expectativas y es confiable.
18.4 Documentación técnica y de usuario
La documentación es una parte clave del proyecto, pues facilita el mantenimiento, la ampliación y
el uso del sistema. Se recomienda generar dos tipos principales:
• Documentación técnica: incluye diagramas de diseño, descripción de la arquitectura,
explicación del código fuente, configuración del entorno y manuales para desarrolladores.
• Documentación de usuario: describe cómo instalar, configurar y usar el sistema. Debe ser
clara y contener ejemplos y capturas de pantalla.
Es conveniente mantener la documentación actualizada durante todo el ciclo de vida del proyecto y
usar herramientas que permitan su generación automática cuando sea posible.
18.5 Presentación del proyecto
La presentación final del proyecto debe resumir todo el trabajo realizado y mostrar los resultados.
Debe incluir:
• Objetivos y alcance del proyecto.
• Diseño y arquitectura general.
• Funcionalidades implementadas.
• Demostración práctica o prototipo funcionando.
• Resultados de las pruebas y validación.
• Conclusiones y posibles mejoras futuras.
Se recomienda preparar material visual como diapositivas, diagramas y demos en vivo. La
presentación debe ser clara, ordenada y enfocada a la audiencia, que puede ser un profesor, cliente o
equipo de trabajo.
Capítulo 19: Recursos adicionales
19.1 Libros recomendados
Para profundizar en Java y mejorar tus habilidades, existen muchos libros que cubren desde los
fundamentos hasta temas avanzados. Algunos de los más recomendados son:
• "Effective Java" de Joshua Bloch: considerado un libro imprescindible para desarrolladores
Java, enseña buenas prácticas, patrones y trucos para escribir código eficiente y mantenible.
• "Java: The Complete Reference" de Herbert Schildt: cubre todo el lenguaje Java, incluyendo
las librerías estándar y conceptos clave, ideal para principiantes y como referencia.
• "Head First Java" de Kathy Sierra y Bert Bates: un libro con un enfoque visual y didáctico
que facilita la comprensión de conceptos básicos y orientados a objetos.
• "Java Concurrency in Practice" de Brian Goetz: para entender en profundidad la
programación concurrente y multihilo en Java.
• "Spring in Action" de Craig Walls: para aprender sobre el popular framework Spring, muy
usado en desarrollo backend con Java.
• "Java Performance: The Definitive Guide" de Scott Oaks: orientado a la optimización y el
análisis del rendimiento de aplicaciones Java.
19.2 Documentación oficial de Java
La documentación oficial es la fuente más confiable y actualizada para aprender y consultar sobre
Java. Está disponible en la página oficial de Oracle:
• Documentación del JDK: [Link]
Aquí encontrarás:
• Tutoriales para principiantes y avanzados.
• API completa de las clases y paquetes estándar.
• Guías sobre herramientas del JDK como javac, javadoc, jvm, etc.
• Documentación específica para cada versión de Java.
Además, el JDK incluye un conjunto de ejemplos y herramientas para probar el código
directamente.
19.3 Foros y comunidades
Participar en comunidades es fundamental para resolver dudas, compartir conocimientos y
mantenerse actualizado. Algunas de las comunidades y foros más importantes para desarrolladores
Java son:
• Stack Overflow ([Link] la comunidad de preguntas y respuestas más
grande, con muchas consultas resueltas sobre Java.
• Reddit - r/java ([Link] un foro activo para discusión sobre noticias,
frameworks y problemas de Java.
• Oracle Java Community ([Link]
foro oficial para desarrolladores Java.
• JavaRanch ([Link] comunidad de desarrolladores Java donde se pueden
hacer preguntas y participar en discusiones.
• GitHub ([Link] no es un foro, pero muchos proyectos Java de código abierto se
alojan aquí, es útil para estudiar código real y contribuir.
19.4 Certificaciones Java
Las certificaciones son una forma formal de validar tus conocimientos y habilidades en Java.
Algunas certificaciones importantes son:
• Oracle Certified Associate, Java SE Programmer (OCAJP): certificación de nivel inicial que
cubre conceptos básicos del lenguaje.
• Oracle Certified Professional, Java SE Programmer (OCPJP): certificación avanzada para
programadores Java con experiencia.
• Oracle Certified Expert en Java EE Web Component Developer: para desarrolladores con
conocimientos en tecnologías web y Java EE.
• Oracle Certified Master, Java SE Developer (OCMJD): certificación de nivel experto para
profesionales con amplio dominio de Java.
Las certificaciones pueden mejorar tu perfil profesional y abrir puertas en el mercado laboral.
19.5 Rutas de especialización: backend, Android, data science, enterprise
Java es un lenguaje versátil que permite especializarse en diferentes áreas de desarrollo:
• Backend: desarrollo de aplicaciones servidor con frameworks como Spring, Hibernate, y
microservicios. Aquí se crean APIs, sistemas de negocio y bases de datos.
• Android: Java es uno de los lenguajes principales para programar aplicaciones móviles
Android, aunque ahora Kotlin está ganando terreno. La especialización incluye desarrollo
UI, manejo de sensores y optimización móvil.
• Data Science: aunque no es el lenguaje más usado en ciencia de datos, Java tiene librerías
para procesamiento de datos, machine learning y Big Data como Weka, Deeplearning4j o
Apache Hadoop.
• Enterprise: desarrollo de aplicaciones empresariales complejas usando Java EE, incluyendo
EJB, JPA, JMS, y servicios web. Se enfocan en sistemas escalables, seguridad y
transacciones distribuidas.
Cada ruta requiere aprender herramientas, frameworks y conceptos específicos. Explorar estas
especializaciones ayuda a orientar tu carrera según tus intereses y el mercado.
Ejercicios
Ejercicio 1
Enunciado: Escribe un programa que imprima "Hola, mundo".
Solución:
public class Ejercicio1 {
public static void main(String[] args) {
[Link]("Hola, mundo");
}
}
Explicación: Se usa [Link] para mostrar texto en consola.
Ejercicio 2
Enunciado: Escribe un programa que sume dos números enteros.
Solución:
public class Ejercicio2 {
public static void main(String[] args) {
int a = 5;
int b = 3;
int suma = a + b;
[Link]("La suma es: " + suma);
}
}
Explicación: Declaramos dos variables enteras y las sumamos.
Ejercicio 3
Enunciado: Escribe un programa que calcule el área de un círculo.
Solución:
public class Ejercicio3 {
public static void main(String[] args) {
double radio = 4.5;
double area = [Link] * radio * radio;
[Link]("Área del círculo: " + area);
}
}
Explicación: Se usa la fórmula A = π * r^2.
Ejercicio 4
Enunciado: Escribe un programa que intercambie los valores de dos variables.
Solución:
public class Ejercicio4 {
public static void main(String[] args) {
int x = 10;
int y = 20;
int temp = x;
x = y;
y = temp;
[Link]("x: " + x + ", y: " + y);
}
}
Explicación: Se usa una variable temporal para intercambiar los valores.
Ejercicio 5
Enunciado: Escribe un programa que determine si un número es par o impar.
Solución:
public class Ejercicio5 {
public static void main(String[] args) {
int numero = 7;
if (numero % 2 == 0) {
[Link]("Es par");
} else {
[Link]("Es impar");
}
}
}
Explicación: Usamos el operador módulo (%) para verificar si hay residuo.
Ejercicio 6
Enunciado: Escribe un programa que muestre los números del 1 al 10.
Solución:
public class Ejercicio6 {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
[Link](i);
}
}
}
Explicación: Usamos un bucle for para contar del 1 al 10.
Ejercicio 7
Enunciado: Escribe un programa que calcule el factorial de un número.
Solución:
public class Ejercicio7 {
public static void main(String[] args) {
int numero = 5;
int factorial = 1;
for (int i = 1; i <= numero; i++) {
factorial *= i;
}
[Link]("Factorial: " + factorial);
}
}
Explicación: El factorial se obtiene multiplicando números consecutivos.
Ejercicio 8
Enunciado: Escribe un programa que convierta grados Celsius a Fahrenheit.
Solución:
public class Ejercicio8 {
public static void main(String[] args) {
double celsius = 25;
double fahrenheit = (celsius * 9/5) + 32;
[Link]("Fahrenheit: " + fahrenheit);
}
}
Explicación: Se usa la fórmula F = C * 9/5 + 32.
Ejercicio 9
Enunciado: Escribe un programa que imprima los primeros 5 múltiplos de 3.
Solución:
public class Ejercicio9 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
[Link](i * 3);
}
}
}
Explicación: Se multiplica 3 por cada número del 1 al 5.
Ejercicio 10
Enunciado: Escribe un programa que calcule el promedio de tres números.
Solución:
public class Ejercicio10 {
public static void main(String[] args) {
double a = 8.5, b = 7.0, c = 9.5;
double promedio = (a + b + c) / 3;
[Link]("Promedio: " + promedio);
}
}
Explicación: Sumamos los tres valores y dividimos entre 3.
Ejercicio 11
Enunciado: Escribe un programa que determine si un número es positivo, negativo o cero.
Solución:
public class Ejercicio11 {
public static void main(String[] args) {
int numero = -4;
if (numero > 0) {
[Link]("Positivo");
} else if (numero < 0) {
[Link]("Negativo");
} else {
[Link]("Cero");
}
}
}
Explicación: Se usan condicionales para comparar el número con 0.
Ejercicio 12
Enunciado: Escribe un programa que imprima los números pares entre 1 y 20.
Solución:
public class Ejercicio12 {
public static void main(String[] args) {
for (int i = 2; i <= 20; i += 2) {
[Link](i);
}
}
}
Explicación: Incrementamos el contador de 2 en 2 para imprimir solo pares.
Ejercicio 13
Enunciado: Escribe un programa que pida un número y muestre su tabla de multiplicar del 1 al 10.
Solución:
import [Link];
public class Ejercicio13 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
for (int i = 1; i <= 10; i++) {
[Link](n + " x " + i + " = " + (n * i));
}
[Link]();
}
}
Explicación: Leemos un número con Scanner y usamos un bucle para multiplicar.
Ejercicio 14
Enunciado: Escribe un programa que cuente cuántos números del 1 al 100 son múltiplos de 5.
Solución:
public class Ejercicio14 {
public static void main(String[] args) {
int contador = 0;
for (int i = 1; i <= 100; i++) {
if (i % 5 == 0) {
contador++;
}
}
[Link]("Múltiplos de 5: " + contador);
}
}
Explicación: Contamos con un if dentro del bucle usando módulo.
Ejercicio 15
Enunciado: Escribe un programa que imprima la suma de los números del 1 al 50.
Solución:
public class Ejercicio15 {
public static void main(String[] args) {
int suma = 0;
for (int i = 1; i <= 50; i++) {
suma += i;
}
[Link]("Suma: " + suma);
}
}
Explicación: Sumamos todos los números en el bucle.
Ejercicio 16
Enunciado: Escribe un programa que reciba un número y diga si es primo o no.
Solución:
import [Link];
public class Ejercicio16 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
boolean esPrimo = true;
if (n <= 1) esPrimo = false;
for (int i = 2; i <= [Link](n); i++) {
if (n % i == 0) {
esPrimo = false;
break;
}
}
if (esPrimo) [Link]("Es primo");
else [Link]("No es primo");
[Link]();
}
}
Explicación: Probamos divisores desde 2 hasta raíz cuadrada.
Ejercicio 17
Enunciado: Escribe un programa que imprima los primeros 10 números Fibonacci.
Solución:
public class Ejercicio17 {
public static void main(String[] args) {
int a = 0, b = 1;
[Link](a);
[Link](b);
for (int i = 3; i <= 10; i++) {
int c = a + b;
[Link](c);
a = b;
b = c;
}
}
}
Explicación: La serie suma los dos números anteriores.
Ejercicio 18
Enunciado: Escribe un programa que convierta una cantidad dada en dólares a euros, considerando
1 USD = 0.85 EUR.
Solución:
import [Link];
public class Ejercicio18 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Dólares: ");
double usd = [Link]();
double eur = usd * 0.85;
[Link]("Euros: " + eur);
[Link]();
}
}
Explicación: Multiplicamos por el tipo de cambio dado.
Ejercicio 19
Enunciado: Escribe un programa que determine si un año es bisiesto.
Solución:
import [Link];
public class Ejercicio19 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Año: ");
int año = [Link]();
boolean esBisiesto = (año % 4 == 0 && año % 100 != 0) || (año % 400 == 0);
if (esBisiesto) [Link]("Es bisiesto");
else [Link]("No es bisiesto");
[Link]();
}
}
Explicación: La regla para años bisiestos es esa.
Ejercicio 20
Enunciado: Escribe un programa que imprima los números del 10 al 1 en orden descendente.
Solución:
public class Ejercicio20 {
public static void main(String[] args) {
for (int i = 10; i >= 1; i--) {
[Link](i);
}
}
}
Explicación: El bucle for cuenta hacia atrás decrementando.
Ejercicio 21
Enunciado: Escribe un programa que reciba un nombre y lo salude.
Solución:
import [Link];
public class Ejercicio21 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Ingrese su nombre: ");
String nombre = [Link]();
[Link]("Hola, " + nombre + "!");
[Link]();
}
}
Explicación: Se usa Scanner para leer texto y concatenar en el saludo.
Ejercicio 22
Enunciado: Escribe un programa que imprima los números del 1 al 100, pero para múltiplos de 3
imprima "Fizz" y para múltiplos de 5 "Buzz".
Solución:
public class Ejercicio22 {
public static void main(String[] args) {
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0) [Link]("Fizz");
else if (i % 5 == 0) [Link]("Buzz");
else [Link](i);
}
}
}
Explicación: Usamos condicionales para verificar los múltiplos.
Ejercicio 23
Enunciado: Escribe un programa que convierta una cadena a mayúsculas.
Solución:
public class Ejercicio23 {
public static void main(String[] args) {
String texto = "hola mundo";
[Link]([Link]());
}
}
Explicación: toUpperCase() convierte texto a mayúsculas.
Ejercicio 24
Enunciado: Escribe un programa que sume los dígitos de un número entero.
Solución:
public class Ejercicio24 {
public static void main(String[] args) {
int numero = 1234;
int suma = 0;
while (numero > 0) {
suma += numero % 10;
numero /= 10;
}
[Link]("Suma de dígitos: " + suma);
}
}
Explicación: Se usa módulo y división para extraer y sumar dígitos.
Ejercicio 25
Enunciado: Escribe un programa que muestre si un carácter es vocal o consonante.
Solución:
public class Ejercicio25 {
public static void main(String[] args) {
char c = 'a';
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
[Link]("Vocal");
} else {
[Link]("Consonante");
}
}
}
Explicación: Comparamos el carácter con las vocales.
Ejercicio 26
Enunciado: Escribe un programa que calcule la potencia de un número base elevado a un exponente
entero positivo.
Solución:
public class Ejercicio26 {
public static void main(String[] args) {
int base = 2;
int exponente = 5;
int resultado = 1;
for (int i = 1; i <= exponente; i++) {
resultado *= base;
}
[Link]("Resultado: " + resultado);
}
}
Explicación: Multiplicamos la base por sí misma exponente veces.
Ejercicio 27
Enunciado: Escribe un programa que imprima los primeros 15 números impares.
Solución:
public class Ejercicio27 {
public static void main(String[] args) {
int count = 0;
int num = 1;
while (count < 15) {
[Link](num);
num += 2;
count++;
}
}
}
Explicación: Los números impares incrementan de 2 en 2 desde 1.
Ejercicio 28
Enunciado: Escribe un programa que reciba una frase y cuente cuántas palabras tiene.
Solución:
import [Link];
public class Ejercicio28 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Ingrese una frase: ");
String frase = [Link]();
String[] palabras = [Link]().split("\s+");
[Link]("Número de palabras: " + [Link]);
[Link]();
}
}
Explicación: Se usa split para dividir la frase en palabras.
Ejercicio 29
Enunciado: Escribe un programa que imprima un triángulo rectángulo de asteriscos de altura 5.
Solución:
public class Ejercicio29 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= i; j++) {
[Link]("*");
}
[Link]();
}
}
}
Explicación: Usamos dos bucles anidados para imprimir el patrón.
Ejercicio 30
Enunciado: Escribe un programa que invierta una cadena dada.
Solución:
public class Ejercicio30 {
public static void main(String[] args) {
String texto = "Java";
String invertido = "";
for (int i = [Link]() - 1; i >= 0; i--) {
invertido += [Link](i);
}
[Link]("Invertido: " + invertido);
}
}
Explicación: Recorremos la cadena desde el final hacia el principio.
Ejercicio 31
Enunciado: Escribe un programa que calcule la suma de los números pares entre 1 y 100.
Solución:
public class Ejercicio31 {
public static void main(String[] args) {
int suma = 0;
for (int i = 2; i <= 100; i += 2) {
suma += i;
}
[Link]("Suma pares: " + suma);
}
}
Explicación: Se suma solo números pares incrementando de 2 en 2.
Ejercicio 32
Enunciado: Escribe un programa que determine si una cadena es un palíndromo (se lee igual al
derecho y al revés).
Solución:
public class Ejercicio32 {
public static void main(String[] args) {
String texto = "anilina";
String invertido = "";
for (int i = [Link]() - 1; i >= 0; i--) {
invertido += [Link](i);
}
if ([Link](invertido)) {
[Link]("Es palíndromo");
} else {
[Link]("No es palíndromo");
}
}
}
Explicación: Comparamos la cadena con su versión invertida ignorando mayúsculas.
Ejercicio 33
Enunciado: Escribe un programa que imprima la suma de los números impares del 1 al 50.
Solución:
public class Ejercicio33 {
public static void main(String[] args) {
int suma = 0;
for (int i = 1; i <= 50; i += 2) {
suma += i;
}
[Link]("Suma impares: " + suma);
}
}
Explicación: Se suma solo números impares incrementando de 2 en 2.
Ejercicio 34
Enunciado: Escribe un programa que calcule el máximo común divisor (MCD) de dos números.
Solución:
public class Ejercicio34 {
public static void main(String[] args) {
int a = 24, b = 36;
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
[Link]("MCD: " + a);
}
}
Explicación: Se usa el algoritmo de Euclides para calcular el MCD.
Ejercicio 35
Enunciado: Escribe un programa que genere un número aleatorio entre 1 y 100.
Solución:
public class Ejercicio35 {
public static void main(String[] args) {
int aleatorio = (int)([Link]() * 100) + 1;
[Link]("Número aleatorio: " + aleatorio);
}
}
Explicación: [Link]() genera un número decimal entre 0 y 1.
Ejercicio 36
Enunciado: Escribe un programa que muestre la fecha y hora actual.
Solución:
import [Link];
public class Ejercicio36 {
public static void main(String[] args) {
LocalDateTime ahora = [Link]();
[Link]("Fecha y hora: " + ahora);
}
}
Explicación: Se usa la clase LocalDateTime para obtener fecha y hora actual.
Ejercicio 37
Enunciado: Escribe un programa que convierta un número entero a binario.
Solución:
public class Ejercicio37 {
public static void main(String[] args) {
int numero = 13;
String binario = [Link](numero);
[Link]("Binario: " + binario);
}
}
Explicación: [Link] convierte el número a cadena binaria.
Ejercicio 38
Enunciado: Escribe un programa que reciba una frase y cuente cuántas vocales tiene.
Solución:
public class Ejercicio38 {
public static void main(String[] args) {
String frase = "Hola mundo";
int contador = 0;
for (int i = 0; i < [Link](); i++) {
char c = [Link]([Link](i));
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
contador++;
}
}
[Link]("Número de vocales: " + contador);
}
}
Explicación: Se verifica cada carácter y se cuenta si es vocal.
Ejercicio 39
Enunciado: Escribe un programa que muestre los primeros 20 números de la serie 2, 4, 8, 16,...
(potencias de 2).
Solución:
public class Ejercicio39 {
public static void main(String[] args) {
int valor = 2;
for (int i = 1; i <= 20; i++) {
[Link](valor);
valor *= 2;
}
}
}
Explicación: Se multiplica por 2 en cada iteración para generar la serie.
Ejercicio 40
Enunciado: Escribe un programa que reciba un número y muestre si es múltiplo de 7.
Solución:
import [Link];
public class Ejercicio40 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n % 7 == 0) {
[Link]("Es múltiplo de 7");
} else {
[Link]("No es múltiplo de 7");
}
[Link]();
}
}
Explicación: Usamos módulo para determinar si el residuo es cero.
Ejercicio 41
Enunciado: Escribe un programa que imprima los números del 1 al 50 que sean múltiplos de 4.
Solución:
public class Ejercicio41 {
public static void main(String[] args) {
for (int i = 1; i <= 50; i++) {
if (i % 4 == 0) {
[Link](i);
}
}
}
}
Explicación: Se verifica el residuo de la división por 4 para filtrar los múltiplos.
Ejercicio 42
Enunciado: Escribe un programa que reciba dos números y muestre cuál es el mayor.
Solución:
import [Link];
public class Ejercicio42 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Ingrese el primer número: ");
int a = [Link]();
[Link]("Ingrese el segundo número: ");
int b = [Link]();
if (a > b) {
[Link](a + " es mayor");
} else if (b > a) {
[Link](b + " es mayor");
} else {
[Link]("Ambos son iguales");
}
[Link]();
}
}
Explicación: Se comparan los dos números usando condicionales.
Ejercicio 43
Enunciado: Escribe un programa que calcule el área de un círculo dado su radio.
Solución:
import [Link];
public class Ejercicio43 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Radio: ");
double radio = [Link]();
double area = [Link] * radio * radio;
[Link]("Área: " + area);
[Link]();
}
}
Explicación: Se aplica la fórmula área = π * r² usando [Link].
Ejercicio 44
Enunciado: Escribe un programa que reciba una cadena y muestre su longitud.
Solución:
import [Link];
public class Ejercicio44 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Ingrese una cadena: ");
String texto = [Link]();
[Link]("Longitud: " + [Link]());
[Link]();
}
}
Explicación: Se usa el método length() para obtener el número de caracteres.
Ejercicio 45
Enunciado: Escribe un programa que imprima los números del 10 al 1 en orden descendente.
Solución:
public class Ejercicio45 {
public static void main(String[] args) {
for (int i = 10; i >= 1; i--) {
[Link](i);
}
}
}
Explicación: Se usa un bucle for que decrece desde 10 hasta 1.
Ejercicio 46
Enunciado: Escribe un programa que determine si un número es positivo, negativo o cero.
Solución:
import [Link];
public class Ejercicio46 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n > 0) {
[Link]("Positivo");
} else if (n < 0) {
[Link]("Negativo");
} else {
[Link]("Cero");
}
[Link]();
}
}
Explicación: Se evalúa el signo del número con condicionales.
Ejercicio 47
Enunciado: Escribe un programa que reciba un número y calcule su factorial.
Solución:
import [Link];
public class Ejercicio47 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int factorial = 1;
for (int i = 1; i <= n; i++) {
factorial *= i;
}
[Link]("Factorial: " + factorial);
[Link]();
}
}
Explicación: Se multiplica desde 1 hasta n para calcular el factorial.
Ejercicio 48
Enunciado: Escribe un programa que convierta una temperatura de grados Celsius a Fahrenheit.
Solución:
import [Link];
public class Ejercicio48 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Grados Celsius: ");
double celsius = [Link]();
double fahrenheit = (celsius * 9 / 5) + 32;
[Link]("Grados Fahrenheit: " + fahrenheit);
[Link]();
}
}
Explicación: Se usa la fórmula para convertir Celsius a Fahrenheit.
Ejercicio 49
Enunciado: Escribe un programa que imprima los números pares entre dos números dados por el
usuario.
Solución:
import [Link];
public class Ejercicio49 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número inicial: ");
int inicio = [Link]();
[Link]("Número final: ");
int fin = [Link]();
for (int i = inicio; i <= fin; i++) {
if (i % 2 == 0) {
[Link](i);
}
}
[Link]();
}
}
Explicación: Se recorren los números entre inicio y fin y se imprimen los pares.
Ejercicio 50
Enunciado: Escribe un programa que reciba un número y muestre si es primo o no.
Solución:
import [Link];
public class Ejercicio50 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
boolean esPrimo = true;
if (n <= 1) {
esPrimo = false;
} else {
for (int i = 2; i <= [Link](n); i++) {
if (n % i == 0) {
esPrimo = false;
break;
}
}
}
if (esPrimo) {
[Link]("Es primo");
} else {
[Link]("No es primo");
}
[Link]();
}
}
Explicación: Se verifica si el número tiene divisores distintos de 1 y él mismo.
Ejercicio 51
Enunciado: Escribe un programa que imprima los números del 1 al 100, pero para múltiplos de 3
imprima "Fizz", para múltiplos de 5 "Buzz" y para múltiplos de ambos "FizzBuzz".
Solución:
public class Ejercicio51 {
public static void main(String[] args) {
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0 && i % 5 == 0) {
[Link]("FizzBuzz");
} else if (i % 3 == 0) {
[Link]("Fizz");
} else if (i % 5 == 0) {
[Link]("Buzz");
} else {
[Link](i);
}
}
}
}
Explicación: Se usan condicionales para verificar múltiplos de 3 y 5.
Ejercicio 52
Enunciado: Escribe un programa que calcule la suma de los dígitos de un número entero.
Solución:
import [Link];
public class Ejercicio52 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
while (n != 0) {
suma += n % 10;
n /= 10;
}
[Link]("Suma de dígitos: " + suma);
[Link]();
}
}
Explicación: Se extraen y suman los dígitos usando módulo y división.
Ejercicio 53
Enunciado: Escribe un programa que reciba una palabra y la imprima en mayúsculas.
Solución:
import [Link];
public class Ejercicio53 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Palabra: ");
String palabra = [Link]();
[Link]([Link]());
[Link]();
}
}
Explicación: Se usa el método toUpperCase() para convertir a mayúsculas.
Ejercicio 54
Enunciado: Escribe un programa que imprima los primeros 10 números Fibonacci.
Solución:
public class Ejercicio54 {
public static void main(String[] args) {
int a = 0, b = 1;
[Link](a);
[Link](b);
for (int i = 3; i <= 10; i++) {
int c = a + b;
[Link](c);
a = b;
b = c;
}
}
}
Explicación: Se calcula la serie sumando los dos números anteriores.
Ejercicio 55
Enunciado: Escribe un programa que reciba un número y muestre su tabla de multiplicar del 1 al 10.
Solución:
import [Link];
public class Ejercicio55 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
for (int i = 1; i <= 10; i++) {
[Link](n + " x " + i + " = " + (n * i));
}
[Link]();
}
}
Explicación: Se multiplica el número por valores del 1 al 10.
Ejercicio 56
Enunciado: Escribe un programa que reciba una frase y cuente cuántas palabras tiene.
Solución:
import [Link];
public class Ejercicio56 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Frase: ");
String frase = [Link]().trim();
if ([Link]()) {
[Link]("0 palabras");
} else {
String[] palabras = [Link]("\s+");
[Link]("Número de palabras: " + [Link]);
}
[Link]();
}
}
Explicación: Se divide la frase por espacios y se cuenta el arreglo.
Ejercicio 57
Enunciado: Escribe un programa que convierta un número decimal a hexadecimal.
Solución:
import [Link];
public class Ejercicio57 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número decimal: ");
int n = [Link]();
String hex = [Link](n);
[Link]("Hexadecimal: " + [Link]());
[Link]();
}
}
Explicación: Se usa [Link] para conversión.
Ejercicio 58
Enunciado: Escribe un programa que imprima los números del 1 al 50 excepto los múltiplos de 7.
Solución:
public class Ejercicio58 {
public static void main(String[] args) {
for (int i = 1; i <= 50; i++) {
if (i % 7 != 0) {
[Link](i);
}
}
}
}
Explicación: Se excluyen números con residuo cero al dividir por 7.
Ejercicio 59
Enunciado: Escribe un programa que reciba un número y muestre la suma de sus cuadrados desde 1
hasta ese número.
Solución:
import [Link];
public class Ejercicio59 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
for (int i = 1; i <= n; i++) {
suma += i * i;
}
[Link]("Suma de cuadrados: " + suma);
[Link]();
}
}
Explicación: Se calcula el cuadrado de cada número y se suma.
Ejercicio 60
Enunciado: Escribe un programa que reciba una cadena y muestre cuántas letras mayúsculas tiene.
Solución:
import [Link];
public class Ejercicio60 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Cadena: ");
String texto = [Link]();
int contador = 0;
for (int i = 0; i < [Link](); i++) {
if ([Link]([Link](i))) {
contador++;
}
}
[Link]("Número de mayúsculas: " + contador);
[Link]();
}
}
Explicación: Se cuenta cada carácter que sea mayúscula con isUpperCase.
Ejercicio 61
Enunciado: Escribe un programa que reciba un número y determine si es par o impar.
Solución:
import [Link];
public class Ejercicio61 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n % 2 == 0) {
[Link]("Es par");
} else {
[Link]("Es impar");
}
[Link]();
}
}
Explicación: Se utiliza el operador módulo para verificar si el número es divisible por 2.
Ejercicio 62
Enunciado: Escribe un programa que reciba una cadena y la imprima invertida.
Solución:
import [Link];
public class Ejercicio62 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Cadena: ");
String texto = [Link]();
String invertida = "";
for (int i = [Link]() - 1; i >= 0; i--) {
invertida += [Link](i);
}
[Link]("Invertida: " + invertida);
[Link]();
}
}
Explicación: Se recorre la cadena desde el final hasta el principio concatenando los caracteres.
Ejercicio 63
Enunciado: Escribe un programa que reciba una lista de números separados por espacios y calcule
su promedio.
Solución:
import [Link];
public class Ejercicio63 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Números separados por espacios: ");
String linea = [Link]();
String[] partes = [Link](" ");
double suma = 0;
for (String parte : partes) {
suma += [Link](parte);
}
double promedio = suma / [Link];
[Link]("Promedio: " + promedio);
[Link]();
}
}
Explicación: Se separan los números, se suman y se divide entre la cantidad para obtener el
promedio.
Ejercicio 64
Enunciado: Escribe un programa que reciba un número y muestre su representación en binario.
Solución:
import [Link];
public class Ejercicio64 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número decimal: ");
int n = [Link]();
String binario = [Link](n);
[Link]("Binario: " + binario);
[Link]();
}
}
Explicación: Se usa [Link] para convertir a binario.
Ejercicio 65
Enunciado: Escribe un programa que reciba dos números y muestre su máximo común divisor
(MCD).
Solución:
import [Link];
public class Ejercicio65 {
public static int mcd(int a, int b) {
if (b == 0) return a;
return mcd(b, a % b);
}
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Primer número: ");
int a = [Link]();
[Link]("Segundo número: ");
int b = [Link]();
[Link]("MCD: " + mcd(a, b));
[Link]();
}
}
Explicación: Se usa el algoritmo de Euclides recursivo para calcular el MCD.
Ejercicio 66
Enunciado: Escribe un programa que reciba un número y muestre su reverso (por ejemplo, 123 →
321).
Solución:
import [Link];
public class Ejercicio66 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int reverso = 0;
while (n != 0) {
reverso = reverso * 10 + n % 10;
n /= 10;
}
[Link]("Reverso: " + reverso);
[Link]();
}
}
Explicación: Se extraen los dígitos de derecha a izquierda y se van agregando en orden inverso.
Ejercicio 67
Enunciado: Escribe un programa que imprima la suma de los números impares entre 1 y 100.
Solución:
public class Ejercicio67 {
public static void main(String[] args) {
int suma = 0;
for (int i = 1; i <= 100; i += 2) {
suma += i;
}
[Link]("Suma de impares: " + suma);
}
}
Explicación: Se suman solo los números impares usando incremento de 2.
Ejercicio 68
Enunciado: Escribe un programa que reciba una cadena y cuente cuántos caracteres tiene sin
espacios.
Solución:
import [Link];
public class Ejercicio68 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Cadena: ");
String texto = [Link]();
int contador = 0;
for (int i = 0; i < [Link](); i++) {
if ([Link](i) != ' ') {
contador++;
}
}
[Link]("Caracteres sin espacios: " + contador);
[Link]();
}
}
Explicación: Se cuentan todos los caracteres excepto espacios.
Ejercicio 69
Enunciado: Escribe un programa que reciba una letra y determine si es una vocal o consonante.
Solución:
import [Link];
public class Ejercicio69 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Letra: ");
char c = [Link]().toLowerCase().charAt(0);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
[Link]("Vocal");
} else if ((c >= 'b' && c <= 'z')) {
[Link]("Consonante");
} else {
[Link]("No es letra válida");
}
[Link]();
}
}
Explicación: Se verifica si el carácter es una vocal o consonante.
Ejercicio 70
Enunciado: Escribe un programa que calcule el área y perímetro de un rectángulo dados su base y
altura.
Solución:
import [Link];
public class Ejercicio70 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Base: ");
double base = [Link]();
[Link]("Altura: ");
double altura = [Link]();
double area = base * altura;
double perimetro = 2 * (base + altura);
[Link]("Área: " + area);
[Link]("Perímetro: " + perimetro);
[Link]();
}
}
Explicación: Se usa fórmula área = base * altura y perímetro = 2*(base + altura).
Ejercicio 71
Enunciado: Escribe un programa que reciba un número y muestre si es positivo, negativo o cero.
Solución:
import [Link];
public class Ejercicio71 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n > 0) {
[Link]("Positivo");
} else if (n < 0) {
[Link]("Negativo");
} else {
[Link]("Cero");
}
[Link]();
}
}
Explicación: Se evalúa la condición del número para clasificarlo.
Ejercicio 72
Enunciado: Escribe un programa que reciba un carácter y determine si es una letra mayúscula.
Solución:
import [Link];
public class Ejercicio72 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Carácter: ");
char c = [Link]().charAt(0);
if ([Link](c)) {
[Link]("Es mayúscula");
} else {
[Link]("No es mayúscula");
}
[Link]();
}
}
Explicación: Se usa [Link] para verificar mayúsculas.
Ejercicio 73
Enunciado: Escribe un programa que imprima los números del 10 al 1 en orden descendente.
Solución:
public class Ejercicio73 {
public static void main(String[] args) {
for (int i = 10; i >= 1; i--) {
[Link](i);
}
}
}
Explicación: Se usa un ciclo for decrementando desde 10 hasta 1.
Ejercicio 74
Enunciado: Escribe un programa que reciba un número y muestre si es un número primo.
Solución:
import [Link];
public class Ejercicio74 {
public static boolean esPrimo(int n) {
if (n <= 1) return false;
for (int i = 2; i <= [Link](n); i++) {
if (n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (esPrimo(n)) {
[Link]("Es primo");
} else {
[Link]("No es primo");
}
[Link]();
}
}
Explicación: Se verifica que el número no tenga divisores entre 2 y la raíz cuadrada.
Ejercicio 75
Enunciado: Escribe un programa que reciba un texto y muestre cuántas vocales contiene.
Solución:
import [Link];
public class Ejercicio75 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Texto: ");
String texto = [Link]().toLowerCase();
int contador = 0;
for (int i = 0; i < [Link](); i++) {
char c = [Link](i);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
contador++;
}
}
[Link]("Número de vocales: " + contador);
[Link]();
}
}
Explicación: Se recorre el texto contando las vocales.
Ejercicio 76
Enunciado: Escribe un programa que reciba una frase y la imprima sin espacios.
Solución:
import [Link];
public class Ejercicio76 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Frase: ");
String frase = [Link]();
String sinEspacios = [Link](" ", "");
[Link]("Sin espacios: " + sinEspacios);
[Link]();
}
}
Explicación: Se usa replace para eliminar los espacios.
Ejercicio 77
Enunciado: Escribe un programa que reciba una lista de números y muestre el mayor.
Solución:
import [Link];
public class Ejercicio77 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Números separados por espacios: ");
String linea = [Link]();
String[] partes = [Link](" ");
int mayor = Integer.MIN_VALUE;
for (String parte : partes) {
int num = [Link](parte);
if (num > mayor) {
mayor = num;
}
}
[Link]("Número mayor: " + mayor);
[Link]();
}
}
Explicación: Se compara cada número para encontrar el mayor.
Ejercicio 78
Enunciado: Escribe un programa que reciba un número y muestre su factorial.
Solución:
import [Link];
public class Ejercicio78 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
long factorial = 1;
for (int i = 2; i <= n; i++) {
factorial *= i;
}
[Link]("Factorial: " + factorial);
[Link]();
}
}
Explicación: Se multiplica sucesivamente desde 1 hasta n para obtener el factorial.
Ejercicio 79
Enunciado: Escribe un programa que reciba una cadena y cuente cuántos dígitos contiene.
Solución:
import [Link];
public class Ejercicio79 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Cadena: ");
String texto = [Link]();
int contador = 0;
for (int i = 0; i < [Link](); i++) {
if ([Link]([Link](i))) {
contador++;
}
}
[Link]("Número de dígitos: " + contador);
[Link]();
}
}
Explicación: Se usa [Link] para contar los dígitos.
Ejercicio 80
Enunciado: Escribe un programa que reciba dos números y muestre su suma, resta, multiplicación y
división.
Solución:
import [Link];
public class Ejercicio80 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número 1: ");
double a = [Link]();
[Link]("Número 2: ");
double b = [Link]();
[Link]("Suma: " + (a + b));
[Link]("Resta: " + (a - b));
[Link]("Multiplicación: " + (a * b));
if (b != 0) {
[Link]("División: " + (a / b));
} else {
[Link]("No se puede dividir entre cero");
}
[Link]();
}
}
Explicación: Se realizan las operaciones básicas y se verifica división por cero.
Ejercicio 81
Enunciado: Escribe un programa que reciba un número entero y muestre si es múltiplo de 3 y 5.
Solución:
import [Link];
public class Ejercicio81 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n % 3 == 0 && n % 5 == 0) {
[Link]("Es múltiplo de 3 y 5");
} else {
[Link]("No es múltiplo de 3 y 5");
}
[Link]();
}
}
Explicación: Se verifica que el número sea divisible tanto por 3 como por 5.
Ejercicio 82
Enunciado: Escribe un programa que reciba una frase y determine cuántas palabras contiene.
Solución:
import [Link];
public class Ejercicio82 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Frase: ");
String frase = [Link]().trim();
if ([Link]()) {
[Link]("Número de palabras: 0");
} else {
String[] palabras = [Link]("\s+");
[Link]("Número de palabras: " + [Link]);
}
[Link]();
}
}
Explicación: Se usa split con expresión regular para dividir por espacios y contar palabras.
Ejercicio 83
Enunciado: Escribe un programa que reciba un número y muestre su tabla de multiplicar del 1 al 10.
Solución:
import [Link];
public class Ejercicio83 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
for (int i = 1; i <= 10; i++) {
[Link](n + " x " + i + " = " + (n * i));
}
[Link]();
}
}
Explicación: Se usa un ciclo para multiplicar el número por 1 hasta 10.
Ejercicio 84
Enunciado: Escribe un programa que reciba un número y muestre si es capicúa (se lee igual al
derecho y al revés).
Solución:
import [Link];
public class Ejercicio84 {
public static boolean esCapicua(int n) {
int original = n;
int reverso = 0;
while (n != 0) {
reverso = reverso * 10 + n % 10;
n /= 10;
}
return original == reverso;
}
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (esCapicua(n)) {
[Link]("Es capicúa");
} else {
[Link]("No es capicúa");
}
[Link]();
}
}
Explicación: Se compara el número original con su reverso.
Ejercicio 85
Enunciado: Escribe un programa que reciba una lista de números y muestre la suma de los pares.
Solución:
import [Link];
public class Ejercicio85 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Números separados por espacios: ");
String linea = [Link]();
String[] partes = [Link](" ");
int suma = 0;
for (String parte : partes) {
int num = [Link](parte);
if (num % 2 == 0) {
suma += num;
}
}
[Link]("Suma de pares: " + suma);
[Link]();
}
}
Explicación: Se suman solo los números que son pares.
Ejercicio 86
Enunciado: Escribe un programa que reciba un número y muestre su raíz cuadrada.
Solución:
import [Link];
public class Ejercicio86 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
double n = [Link]();
if (n >= 0) {
[Link]("Raíz cuadrada: " + [Link](n));
} else {
[Link]("No se puede calcular la raíz cuadrada de un número negativo");
}
[Link]();
}
}
Explicación: Se usa [Link] y se verifica que el número sea positivo.
Ejercicio 87
Enunciado: Escribe un programa que reciba un número entero y muestre la suma de sus dígitos.
Solución:
import [Link];
public class Ejercicio87 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
while (n != 0) {
suma += n % 10;
n /= 10;
}
[Link]("Suma de dígitos: " + suma);
[Link]();
}
}
Explicación: Se extraen y suman cada dígito dividiendo sucesivamente entre 10.
Ejercicio 88
Enunciado: Escribe un programa que reciba un número y muestre la cantidad de dígitos que tiene.
Solución:
import [Link];
public class Ejercicio88 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int contador = 0;
if (n == 0) contador = 1;
while (n != 0) {
n /= 10;
contador++;
}
[Link]("Cantidad de dígitos: " + contador);
[Link]();
}
}
Explicación: Se cuenta cuántas veces se puede dividir el número entre 10 hasta llegar a 0.
Ejercicio 89
Enunciado: Escribe un programa que reciba una cadena y muestre si es un palíndromo (se lee igual
al derecho y al revés, ignorando espacios).
Solución:
import [Link];
public class Ejercicio89 {
public static boolean esPalindromo(String texto) {
texto = [Link](" ", "").toLowerCase();
int i = 0;
int j = [Link]() - 1;
while (i < j) {
if ([Link](i) != [Link](j)) return false;
i++;
j--;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Texto: ");
String texto = [Link]();
if (esPalindromo(texto)) {
[Link]("Es palíndromo");
} else {
[Link]("No es palíndromo");
}
[Link]();
}
}
Explicación: Se compara la cadena de adelante hacia atrás ignorando espacios y mayúsculas.
Ejercicio 90
Enunciado: Escribe un programa que reciba un número y muestre su valor absoluto.
Solución:
import [Link];
public class Ejercicio90 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
[Link]("Valor absoluto: " + [Link](n));
[Link]();
}
}
Explicación: Se usa [Link] para obtener el valor absoluto del número.
Ejercicio 91
Enunciado: Escribe un programa que reciba un número y muestre si es par o impar.
Solución:
import [Link];
public class Ejercicio91 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n % 2 == 0) {
[Link]("Es par");
} else {
[Link]("Es impar");
}
[Link]();
}
}
Explicación: Se usa el operador módulo para determinar si el número es divisible por 2.
Ejercicio 92
Enunciado: Escribe un programa que reciba dos números y muestre cuál es mayor.
Solución:
import [Link];
public class Ejercicio92 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número 1: ");
int a = [Link]();
[Link]("Número 2: ");
int b = [Link]();
if (a > b) {
[Link](a + " es mayor");
} else if (b > a) {
[Link](b + " es mayor");
} else {
[Link]("Son iguales");
}
[Link]();
}
}
Explicación: Se compara ambos números para determinar cuál es mayor o si son iguales.
Ejercicio 93
Enunciado: Escribe un programa que reciba un número y muestre la suma de los números del 1
hasta ese número.
Solución:
import [Link];
public class Ejercicio93 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
for (int i = 1; i <= n; i++) {
suma += i;
}
[Link]("Suma: " + suma);
[Link]();
}
}
Explicación: Se suman todos los números desde 1 hasta n usando un ciclo for.
Ejercicio 94
Enunciado: Escribe un programa que reciba un texto y muestre el texto en mayúsculas.
Solución:
import [Link];
public class Ejercicio94 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Texto: ");
String texto = [Link]();
[Link]([Link]());
[Link]();
}
}
Explicación: Se usa el método toUpperCase para convertir el texto a mayúsculas.
Ejercicio 95
Enunciado: Escribe un programa que reciba un número y muestre si es múltiplo de 7.
Solución:
import [Link];
public class Ejercicio95 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (n % 7 == 0) {
[Link]("Es múltiplo de 7");
} else {
[Link]("No es múltiplo de 7");
}
[Link]();
}
}
Explicación: Se verifica que el número sea divisible por 7.
Ejercicio 96
Enunciado: Escribe un programa que reciba un número y muestre la suma de sus números pares
desde 0 hasta ese número.
Solución:
import [Link];
public class Ejercicio96 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
for (int i = 0; i <= n; i += 2) {
suma += i;
}
[Link]("Suma de pares: " + suma);
[Link]();
}
}
Explicación: Se suma solo números pares usando incremento de 2.
Ejercicio 97
Enunciado: Escribe un programa que reciba un texto y muestre la cantidad de letras 'a' que contiene.
Solución:
import [Link];
public class Ejercicio97 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Texto: ");
String texto = [Link]().toLowerCase();
int contador = 0;
for (int i = 0; i < [Link](); i++) {
if ([Link](i) == 'a') {
contador++;
}
}
[Link]("Cantidad de letras 'a': " + contador);
[Link]();
}
}
Explicación: Se cuenta cuántas veces aparece la letra 'a' en el texto.
Ejercicio 98
Enunciado: Escribe un programa que reciba un número y muestre la suma de los números impares
desde 1 hasta ese número.
Solución:
import [Link];
public class Ejercicio98 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
int suma = 0;
for (int i = 1; i <= n; i += 2) {
suma += i;
}
[Link]("Suma de impares: " + suma);
[Link]();
}
}
Explicación: Se suma solo números impares incrementando de 2 en 2.
Ejercicio 99
Enunciado: Escribe un programa que reciba un número y muestre si es un número perfecto (la suma
de sus divisores propios es igual al número).
Solución:
import [Link];
public class Ejercicio99 {
public static boolean esPerfecto(int n) {
int suma = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
suma += i;
}
}
return suma == n;
}
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Número: ");
int n = [Link]();
if (esPerfecto(n)) {
[Link]("Es número perfecto");
} else {
[Link]("No es número perfecto");
}
[Link]();
}
}
Explicación: Se suman los divisores propios y se compara con el número.
Ejercicio 100
Enunciado: Escribe un programa que reciba dos cadenas y determine si son iguales (ignorando
mayúsculas y minúsculas).
Solución:
import [Link];
public class Ejercicio100 {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
[Link]("Cadena 1: ");
String c1 = [Link]();
[Link]("Cadena 2: ");
String c2 = [Link]();
if ([Link](c2)) {
[Link]("Son iguales");
} else {
[Link]("No son iguales");
}
[Link]();
}
}
Explicación: Se usa equalsIgnoreCase para comparar cadenas ignorando mayúsculas y minúsculas.
Epílogo
Llegar al final de este libro es solo el comienzo de tu viaje en el mundo de la programación con
Java. A lo largo de estas páginas, has explorado desde los fundamentos básicos hasta conceptos más
avanzados, aprendiendo a pensar como un desarrollador y a resolver problemas con lógica y
creatividad.
Java no es solo un lenguaje de programación; es una plataforma que impulsa aplicaciones desde
pequeños programas hasta sistemas empresariales complejos, móviles y más allá. La versatilidad y
robustez de Java te ofrecen infinitas oportunidades para crecer, innovar y contribuir en un campo en
constante evolución.
Recuerda que dominar Java no significa solo conocer su sintaxis o librerías, sino también cultivar el
hábito de aprender, experimentar y adaptarte. El código que escribas será un reflejo de tu
perseverancia y pasión.
Sigue practicando, construyendo proyectos, leyendo código de otros y manteniéndote actualizado
con las nuevas versiones y tendencias. La comunidad de Java es amplia y colaborativa, y siempre
habrá espacio para nuevas ideas y soluciones.
Gracias por acompañarme en esta travesía. Ahora, toma tu teclado, abre tu entorno de desarrollo, y
crea el futuro que imaginas con Java.
¡Feliz programación!