Certificado de Java OOP

10h 0m

Certificado Java con ejercicios de programación. Domina la programación en Java y obtén un certificado al finalizar el curso.

Accede GRATIS y certifícate

La programación orientada a objetos (OOP) es un paradigma fundamental en el desarrollo de software moderno que permite crear aplicaciones robustas, mantenibles y escalables. Java, como lenguaje de programación orientado a objetos por excelencia, implementa este paradigma de manera completa y consistente, convirtiéndolo en una herramienta esencial para desarrolladores profesionales.

Fundamentos de la programación orientada a objetos en Java

Java se diseñó desde sus inicios como un lenguaje puramente orientado a objetos, lo que significa que prácticamente todo en Java es un objeto (con algunas excepciones como los tipos primitivos). Este enfoque permite modelar sistemas complejos de manera intuitiva, representando entidades del mundo real como objetos con características (atributos) y comportamientos (métodos).

La OOP en Java se sustenta en cuatro pilares fundamentales:

  • Encapsulación: Permite ocultar los detalles internos de implementación y exponer solo lo necesario.
  • Herencia: Facilita la reutilización de código y la creación de jerarquías de clases.
  • Polimorfismo: Proporciona flexibilidad al permitir que objetos de diferentes clases respondan de manera distinta al mismo mensaje.
  • Abstracción: Permite centrarse en lo que hace un objeto en lugar de cómo lo hace.

Clases y objetos: la base de Java

En Java, todo comienza con las clases, que son plantillas o moldes que definen la estructura y comportamiento de los objetos. Una clase encapsula datos (atributos) y comportamientos (métodos) relacionados en una única unidad.

public class Automovil {
    // Atributos
    private String marca;
    private String modelo;
    private int año;
    
    // Constructor
    public Automovil(String marca, String modelo, int año) {
        this.marca = marca;
        this.modelo = modelo;
        this.año = año;
    }
    
    // Métodos
    public void arrancar() {
        System.out.println("El automóvil está arrancando");
    }
    
    public void detener() {
        System.out.println("El automóvil se ha detenido");
    }
}

A partir de una clase, podemos crear instancias u objetos concretos:

Automovil miCoche = new Automovil("Toyota", "Corolla", 2023);
miCoche.arrancar();

Encapsulación y control de acceso

La encapsulación es uno de los conceptos más importantes en Java, permitiendo ocultar los detalles internos de implementación y proteger la integridad de los datos. Mediante los modificadores de acceso (private, protected, public), podemos controlar qué partes de nuestro código son accesibles desde otras clases.

public class CuentaBancaria {
    // Atributos encapsulados (privados)
    private String numeroCuenta;
    private double saldo;
    
    // Métodos públicos para acceder a los atributos (getters)
    public String getNumeroCuenta() {
        return numeroCuenta;
    }
    
    public double getSaldo() {
        return saldo;
    }
    
    // Métodos públicos para modificar los atributos (setters)
    public void depositar(double cantidad) {
        if (cantidad > 0) {
            saldo += cantidad;
        }
    }
    
    public boolean retirar(double cantidad) {
        if (cantidad > 0 && saldo >= cantidad) {
            saldo -= cantidad;
            return true;
        }
        return false;
    }
}

Herencia y extensibilidad

La herencia permite crear nuevas clases basadas en clases existentes, heredando sus atributos y métodos. Esto facilita la reutilización de código y la creación de jerarquías de clases que representan relaciones "es un" entre objetos.

// Clase base o superclase
public class Empleado {
    protected String nombre;
    protected double salarioBase;
    
    public Empleado(String nombre, double salarioBase) {
        this.nombre = nombre;
        this.salarioBase = salarioBase;
    }
    
    public double calcularSalario() {
        return salarioBase;
    }
}

// Clase derivada o subclase
public class Gerente extends Empleado {
    private double bono;
    
    public Gerente(String nombre, double salarioBase, double bono) {
        super(nombre, salarioBase); // Llamada al constructor de la superclase
        this.bono = bono;
    }
    
    @Override
    public double calcularSalario() {
        return super.calcularSalario() + bono;
    }
}

Abstracción mediante clases abstractas e interfaces

Java proporciona dos mecanismos principales para implementar la abstracción: clases abstractas e interfaces.

Las clases abstractas permiten definir una base común para un grupo de subclases, pudiendo contener métodos concretos y abstractos:

public abstract class Figura {
    // Método abstracto (sin implementación)
    public abstract double calcularArea();
    
    // Método concreto (con implementación)
    public void mostrarInformacion() {
        System.out.println("Área: " + calcularArea());
    }
}

public class Circulo extends Figura {
    private double radio;
    
    public Circulo(double radio) {
        this.radio = radio;
    }
    
    @Override
    public double calcularArea() {
        return Math.PI * radio * radio;
    }
}

Las interfaces definen contratos que las clases deben cumplir, especificando qué métodos deben implementar sin definir cómo:

public interface Dibujable {
    void dibujar();
    void cambiarColor(String color);
}

public class Rectangulo implements Dibujable {
    private double ancho;
    private double alto;
    
    @Override
    public void dibujar() {
        System.out.println("Dibujando un rectángulo");
    }
    
    @Override
    public void cambiarColor(String color) {
        System.out.println("Cambiando color a: " + color);
    }
}

Polimorfismo y flexibilidad

El polimorfismo permite tratar objetos de diferentes clases a través de una interfaz común, proporcionando flexibilidad y extensibilidad al código. En Java, esto se logra principalmente mediante la sobrecarga de métodos y la sobreescritura.

La sobrecarga de métodos permite definir múltiples métodos con el mismo nombre pero diferentes parámetros:

public class Calculadora {
    public int sumar(int a, int b) {
        return a + b;
    }
    
    public double sumar(double a, double b) {
        return a + b;
    }
    
    public int sumar(int a, int b, int c) {
        return a + b + c;
    }
}

La sobreescritura de métodos permite a una subclase proporcionar una implementación específica de un método definido en su superclase:

public class Animal {
    public void hacerSonido() {
        System.out.println("El animal hace un sonido");
    }
}

public class Perro extends Animal {
    @Override
    public void hacerSonido() {
        System.out.println("El perro ladra");
    }
}

public class Gato extends Animal {
    @Override
    public void hacerSonido() {
        System.out.println("El gato maulla");
    }
}

El polimorfismo nos permite tratar objetos específicos a través de referencias más generales:

Animal miMascota = new Perro();
miMascota.hacerSonido(); // Imprime "El perro ladra"

miMascota = new Gato();
miMascota.hacerSonido(); // Imprime "El gato maulla"

Manejo de entrada/salida con la clase Scanner

La clase Scanner facilita la lectura de datos desde diversas fuentes, como la entrada estándar (teclado), archivos o cadenas de texto:

import java.util.Scanner;

public class EntradaUsuario {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("Ingrese su nombre: ");
        String nombre = scanner.nextLine();
        
        System.out.print("Ingrese su edad: ");
        int edad = scanner.nextInt();
        
        System.out.println("Hola " + nombre + ", tienes " + edad + " años.");
        
        scanner.close(); // Importante cerrar el scanner
    }
}

Manipulación de cadenas con la clase String

Java proporciona la clase String con numerosos métodos para manipular texto de manera eficiente:

public class ManipulacionTexto {
    public static void main(String[] args) {
        String texto = "Java es un lenguaje orientado a objetos";
        
        // Longitud de la cadena
        System.out.println("Longitud: " + texto.length());
        
        // Conversión a mayúsculas/minúsculas
        System.out.println("Mayúsculas: " + texto.toUpperCase());
        System.out.println("Minúsculas: " + texto.toLowerCase());
        
        // Búsqueda y reemplazo
        System.out.println("Contiene 'objetos': " + texto.contains("objetos"));
        System.out.println("Reemplazo: " + texto.replace("Java", "Python"));
        
        // Extracción de subcadenas
        System.out.println("Subcadena: " + texto.substring(0, 4));
        
        // División en tokens
        String[] palabras = texto.split(" ");
        System.out.println("Primera palabra: " + palabras[0]);
    }
}

Enumeraciones (Enums)

Las enumeraciones permiten definir un conjunto fijo de constantes con nombre, mejorando la legibilidad y seguridad del código:

public enum DiaSemana {
    LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO
}

public class ProgramacionSemanal {
    public void configurarAlarma(DiaSemana dia) {
        switch (dia) {
            case LUNES:
            case MARTES:
            case MIERCOLES:
            case JUEVES:
            case VIERNES:
                System.out.println("Alarma configurada para las 7:00 AM");
                break;
            case SABADO:
            case DOMINGO:
                System.out.println("Alarma configurada para las 9:00 AM");
                break;
        }
    }
}

Manejo de excepciones

El manejo de excepciones permite controlar errores y situaciones anómalas de forma elegante, mejorando la robustez de las aplicaciones:

public class DivisionSegura {
    public static double dividir(int numerador, int denominador) {
        try {
            return numerador / denominador;
        } catch (ArithmeticException e) {
            System.err.println("Error: División por cero");
            return 0;
        } finally {
            System.out.println("Operación de división finalizada");
        }
    }
    
    public static void main(String[] args) {
        System.out.println(dividir(10, 2)); // 5.0
        System.out.println(dividir(10, 0)); // 0.0 (con mensaje de error)
    }
}

También podemos crear nuestras propias excepciones personalizadas:

public class SaldoInsuficienteException extends Exception {
    public SaldoInsuficienteException(String mensaje) {
        super(mensaje);
    }
}

public class CuentaBancaria {
    private double saldo;
    
    public void retirar(double cantidad) throws SaldoInsuficienteException {
        if (cantidad > saldo) {
            throw new SaldoInsuficienteException("Saldo insuficiente para realizar la operación");
        }
        saldo -= cantidad;
    }
}

Colecciones en Java

Java proporciona un potente framework de colecciones para almacenar y manipular grupos de objetos. Las principales interfaces son List, Set y Map.

Listas (List)

Las listas mantienen un orden específico y permiten elementos duplicados:

import java.util.ArrayList;
import java.util.List;

public class EjemploListas {
    public static void main(String[] args) {
        List<String> lenguajes = new ArrayList<>();
        
        // Agregar elementos
        lenguajes.add("Java");
        lenguajes.add("Python");
        lenguajes.add("JavaScript");
        lenguajes.add("Java"); // Permite duplicados
        
        // Acceder por índice
        System.out.println("Primer elemento: " + lenguajes.get(0));
        
        // Recorrer la lista
        for (String lenguaje : lenguajes) {
            System.out.println(lenguaje);
        }
        
        // Eliminar elemento
        lenguajes.remove("Python");
        
        // Tamaño de la lista
        System.out.println("Tamaño: " + lenguajes.size());
    }
}

Conjuntos (Set)

Los conjuntos no permiten elementos duplicados y generalmente no mantienen un orden específico:

import java.util.HashSet;
import java.util.Set;

public class EjemploConjuntos {
    public static void main(String[] args) {
        Set<String> frutas = new HashSet<>();
        
        // Agregar elementos
        frutas.add("Manzana");
        frutas.add("Banana");
        frutas.add("Naranja");
        frutas.add("Manzana"); // No se agregará (duplicado)
        
        // Verificar si contiene un elemento
        System.out.println("¿Contiene Banana? " + frutas.contains("Banana"));
        
        // Recorrer el conjunto
        for (String fruta : frutas) {
            System.out.println(fruta);
        }
        
        // Eliminar elemento
        frutas.remove("Naranja");
        
        // Tamaño del conjunto
        System.out.println("Tamaño: " + frutas.size());
    }
}

Mapas (Map)

Los mapas almacenan pares clave-valor, donde cada clave es única:

import java.util.HashMap;
import java.util.Map;

public class EjemploMapas {
    public static void main(String[] args) {
        Map<String, Integer> edades = new HashMap<>();
        
        // Agregar elementos
        edades.put("Ana", 25);
        edades.put("Carlos", 30);
        edades.put("María", 28);
        
        // Acceder por clave
        System.out.println("Edad de Carlos: " + edades.get("Carlos"));
        
        // Verificar si contiene una clave
        System.out.println("¿Contiene a Pedro? " + edades.containsKey("Pedro"));
        
        // Recorrer el mapa
        for (Map.Entry<String, Integer> entrada : edades.entrySet()) {
            System.out.println(entrada.getKey() + ": " + entrada.getValue());
        }
        
        // Eliminar elemento
        edades.remove("Ana");
        
        // Tamaño del mapa
        System.out.println("Tamaño: " + edades.size());
    }
}

Implementación de operaciones CRUD en Java

Las operaciones CRUD (Create, Read, Update, Delete) son fundamentales en el desarrollo de aplicaciones. En Java, podemos implementarlas utilizando colecciones como ArrayList o HashMap.

CRUD con ArrayList

import java.util.ArrayList;
import java.util.List;

public class ClienteService {
    private List<Cliente> clientes = new ArrayList<>();
    
    // Create
    public void crearCliente(Cliente cliente) {
        clientes.add(cliente);
    }
    
    // Read
    public Cliente buscarPorId(int id) {
        for (Cliente cliente : clientes) {
            if (cliente.getId() == id) {
                return cliente;
            }
        }
        return null;
    }
    
    public List<Cliente> listarTodos() {
        return new ArrayList<>(clientes);
    }
    
    // Update
    public boolean actualizarCliente(Cliente cliente) {
        for (int i = 0; i < clientes.size(); i++) {
            if (clientes.get(i).getId() == cliente.getId()) {
                clientes.set(i, cliente);
                return true;
            }
        }
        return false;
    }
    
    // Delete
    public boolean eliminarCliente(int id) {
        return clientes.removeIf(cliente -> cliente.getId() == id);
    }
}

class Cliente {
    private int id;
    private String nombre;
    private String email;
    
    // Constructor, getters y setters
}

CRUD con HashMap

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class ProductoService {
    private Map<Integer, Producto> productos = new HashMap<>();
    
    // Create
    public void crearProducto(Producto producto) {
        productos.put(producto.getId(), producto);
    }
    
    // Read
    public Producto buscarPorId(int id) {
        return productos.get(id);
    }
    
    public Collection<Producto> listarTodos() {
        return productos.values();
    }
    
    // Update
    public boolean actualizarProducto(Producto producto) {
        if (productos.containsKey(producto.getId())) {
            productos.put(producto.getId(), producto);
            return true;
        }
        return false;
    }
    
    // Delete
    public boolean eliminarProducto(int id) {
        return productos.remove(id) != null;
    }
}

class Producto {
    private int id;
    private String nombre;
    private double precio;
    
    // Constructor, getters y setters
}

La programación orientada a objetos en Java proporciona un marco sólido para desarrollar aplicaciones estructuradas, mantenibles y escalables. Dominar estos conceptos fundamentales te permitirá crear soluciones robustas y eficientes para una amplia variedad de problemas de programación.

Empezar curso GRATIS

Tutoriales de programación en este certificado

Completa estas lecciones de programación para obtener tu certificado de superación

Ejercicios de programación de Java OOP

Completa estos ejercicios de programación para obtener tu certificado de superación

Otros cursos de programación con certificado

Supera todos los retos de Java OOP y obtén estos certificados de superación para mejorar tu currículum y tu empleabilidad.

Tecnologías que aprenderás

Java OOP

Al finalizar este curso obtendrás

Certificado de superación en Java OOP

Certificado de superación en Java OOP

Tras completar todas las lecciones y ejercicios del curso Java OOP se te genera un enlace con tu certificado para que lo puedas descargar o compartir directamente en cualquier plataforma, siempre accesible.

Accede a todas certificaciones