El Objeto en POO: qué es y cómo se crea en Java

📅 Actualizado en febrero 2026 ✍️ Ángel López ⏱️ 15 min de lectura ✓ Nivel principiante ★ ★ ★ ★ ★ (5/5)

📦 ¿Qué es un objeto en programación?

En la Programación Orientada a Objetos (POO), un objeto es la entidad fundamental sobre la que gira todo el paradigma. Un objeto es un ejemplar concreto de una clase: si la clase Coche define las características generales de cualquier coche, un objeto sería un coche específico —por ejemplo, un Toyota Corolla rojo con 45.000 km—. Cada objeto posee datos propios (sus atributos) y puede ejecutar acciones (sus métodos).

La POO modela problemas del mundo real representándolos como colecciones de objetos que interactúan entre sí a través de mensajes. Este enfoque facilita la organización del código, la reutilización de componentes y el mantenimiento de sistemas complejos. En Java, prácticamente todo es un objeto: las cadenas de texto, los arrays, las ventanas gráficas, las conexiones de red y, por supuesto, las entidades de negocio que el programador define.

📘 Nota: Los únicos elementos que no son objetos en Java son los tipos primitivos (int, double, boolean, char, etc.), aunque cada uno dispone de una clase envolvente (wrapper) como Integer o Double que sí son objetos.

🌍 Objetos del mundo real vs. objetos en software

Para entender los objetos en programación, resulta útil partir de una analogía con el mundo físico. Un perro, un libro, una factura o un pedido de comercio electrónico son entidades con características observables y acciones que pueden realizar o recibir. En la POO, esa misma idea se traslada al código:

Concepto del mundo real Equivalencia en POO (Java) Ejemplo
Categoría o tipo de cosa Clase class Coche { ... }
Cosa concreta e individual Objeto (instancia) Coche miCoche = new Coche();
Características (color, peso, marca) Atributos (campos, propiedades) miCoche.color = "rojo";
Acciones (arrancar, frenar) Métodos miCoche.arrancar();

Esta correspondencia directa entre el dominio del problema y el código es una de las grandes ventajas de la POO: el software refleja la realidad de manera natural, lo que facilita tanto el diseño como la comunicación entre desarrolladores y usuarios de negocio.

🔑 Estado, comportamiento e identidad

Todo objeto en Java se define por tres características esenciales que lo distinguen de cualquier otro elemento del programa:

▶️ Estado

El estado de un objeto es el conjunto de valores que almacenan sus atributos en un momento dado. Por ejemplo, un objeto CuentaBancaria puede tener un saldo de 1.500,00 € y un titular llamado «Ana García». El estado cambia cuando un método modifica alguno de esos valores (por ejemplo, al realizar un ingreso o una retirada).

🔹 Comportamiento

El comportamiento es el conjunto de operaciones que el objeto puede ejecutar, definidas por los métodos de su clase. En el ejemplo de la cuenta bancaria, el comportamiento incluye ingresar(), retirar() y consultarSaldo(). El comportamiento puede modificar el estado propio del objeto o el de otros objetos con los que interactúe.

🔸 Identidad

La identidad es lo que distingue a un objeto de cualquier otro, incluso si ambos tienen exactamente el mismo estado. En Java, la identidad viene dada por la referencia en memoria: dos objetos pueden tener los mismos valores en todos sus atributos y, sin embargo, ser objetos distintos porque ocupan posiciones diferentes en el heap.

Java
// Dos objetos con el mismo estado pero distinta identidad
Coche cocheA = new Coche("Toyota", "Rojo");
Coche cocheB = new Coche("Toyota", "Rojo");

System.out.println(cocheA == cocheB);      // false → distinta identidad
System.out.println(cocheA.equals(cocheB)); // true  → si equals() está sobrescrito

🏗️ Cómo crear objetos en Java con new

En Java, la creación de un objeto requiere dos pasos conceptuales que habitualmente se realizan en una sola línea:

▶️ Paso 1: Declarar la variable de referencia

Se indica el tipo (la clase) y el nombre de la variable. En este punto, la variable existe pero aún no apunta a ningún objeto; su valor es null.

🔹 Paso 2: Instanciar el objeto con new

El operador new realiza tres acciones internas: reserva memoria en el heap para el nuevo objeto, invoca el constructor de la clase para inicializar los atributos y devuelve la referencia (dirección de memoria) al objeto recién creado.

Java
// Paso a paso
Coche miCoche;                          // 1. Declaración (miCoche vale null)
miCoche = new Coche("Seat", "Blanco");  // 2. Instanciación (ahora apunta al objeto)

// Todo en una línea (forma más habitual)
Coche miCoche = new Coche("Seat", "Blanco");
💡 Buena práctica: Siempre que sea posible, declara e instancia en la misma línea. Esto reduce el riesgo de usar accidentalmente una referencia null, que provocaría un NullPointerException.

🔹 Uso de constructores con parámetros

Una clase puede definir múltiples constructores (sobrecarga de constructores), cada uno con diferentes parámetros. Esto permite crear objetos con distintos grados de inicialización:

Java
public class Producto {
    private String nombre;
    private double precio;
    private int stock;

    // Constructor sin parámetros (valores por defecto)
    public Producto() {
        this.nombre = "Sin nombre";
        this.precio = 0.0;
        this.stock  = 0;
    }

    // Constructor con todos los parámetros
    public Producto(String nombre, double precio, int stock) {
        this.nombre = nombre;
        this.precio = precio;
        this.stock  = stock;
    }

    // Constructor parcial (solo nombre y precio)
    public Producto(String nombre, double precio) {
        this(nombre, precio, 0); // Reutiliza el constructor completo
    }
}

// Tres formas de crear un Producto
Producto p1 = new Producto();                          // "Sin nombre", 0.0, 0
Producto p2 = new Producto("Teclado", 49.99, 150);     // Todos los datos
Producto p3 = new Producto("Ratón", 19.99);            // Sin stock inicial

🔬 Anatomía de un objeto: atributos y métodos

Un objeto es, en esencia, una cápsula que agrupa datos y las operaciones que actúan sobre esos datos. Esta separación en dos partes —atributos y métodos— es la base del encapsulamiento, uno de los cuatro pilares de la POO.

▶️ Atributos (campos o propiedades)

Los atributos son las variables de instancia que almacenan el estado del objeto. Cada objeto tiene su propia copia de estos valores. Por convención, los atributos se declaran como private para proteger el estado interno:

Java
public class Empleado {
    // Atributos (estado del objeto)
    private String nombre;
    private String departamento;
    private double salario;
    private boolean activo;
}

🔹 Métodos (operaciones)

Los métodos definen el comportamiento del objeto. A través de ellos se puede consultar o modificar el estado de forma controlada. Los métodos más comunes son los getters (lectura), setters (escritura) y los métodos de lógica de negocio:

Java
public class Empleado {
    private String nombre;
    private double salario;
    private boolean activo;

    // Constructor
    public Empleado(String nombre, double salario) {
        this.nombre  = nombre;
        this.salario = salario;
        this.activo  = true;
    }

    // Getter
    public String getNombre() {
        return nombre;
    }

    // Setter con validación
    public void setSalario(double nuevoSalario) {
        if (nuevoSalario >= 0) {
            this.salario = nuevoSalario;
        }
    }

    // Método de lógica de negocio
    public double calcularSalarioAnual() {
        return activo ? salario * 14 : 0; // 14 pagas en España
    }

    // Representación textual del objeto
    @Override
    public String toString() {
        return nombre + " | Salario: " + salario + "€ | Activo: " + activo;
    }
}
⚠️ Precaución: Nunca accedas directamente a los atributos de un objeto desde fuera de su clase (por ejemplo, miEmpleado.salario = -500). Utiliza siempre setters con validación para garantizar que el estado del objeto sea consistente en todo momento.

🧠 Referencias, memoria heap y stack

Comprender cómo Java gestiona los objetos en memoria es esencial para evitar errores sutiles. A diferencia de los tipos primitivos, los objetos no se almacenan directamente en las variables: lo que la variable contiene es una referencia (una especie de dirección postal) al objeto real, que reside en el heap.

Zona de memoria Almacena Gestión
Stack (pila) Variables locales, referencias a objetos, parámetros de métodos Automática (LIFO): se libera al salir del método
Heap (montículo) Los objetos propiamente dichos (atributos + datos) Garbage Collector: libera objetos sin referencias
Java
// Ejemplo de referencias compartidas
Coche a = new Coche("BMW", "Negro");  // 'a' apunta al objeto en heap
Coche b = a;                           // 'b' apunta al MISMO objeto

b.setColor("Azul");                    // Modifica el objeto compartido
System.out.println(a.getColor());      // "Azul" → ambas referencias ven el cambio

// Ahora 'a' apunta a un objeto nuevo
a = new Coche("Audi", "Gris");        // 'a' cambia; 'b' sigue apuntando al BMW azul
System.out.println(b.getMarca());      // "BMW" → el objeto original sigue vivo
📘 Concepto clave: En Java, cuando asignas una variable de tipo objeto a otra (b = a), no se copia el objeto, sino únicamente la referencia. Ambas variables apuntan al mismo objeto. Para obtener una copia independiente necesitas implementar el método clone() o un constructor de copia.

♻️ Ciclo de vida de un objeto

Los objetos en Java nacen, viven y mueren siguiendo un ciclo bien definido que el programador debe comprender para escribir código eficiente y libre de fugas de memoria:

▶️ 1. Creación (instanciación)

El operador new reserva memoria en el heap e invoca el constructor. El objeto queda listo para su uso, con sus atributos inicializados.

🔹 2. Uso (vida activa)

El objeto recibe mensajes (llamadas a métodos), su estado cambia y puede interactuar con otros objetos. Mientras al menos una variable mantenga una referencia al objeto, este permanece «vivo».

🔸 3. Inaccesibilidad

Cuando ninguna variable del programa mantiene una referencia al objeto (por ejemplo, porque la variable salió de ámbito o se le asignó null), el objeto se convierte en elegible para la recolección de basura.

➡️ 4. Recolección de basura (Garbage Collection)

El Garbage Collector (GC) de la JVM detecta automáticamente los objetos inaccesibles y libera su memoria. El programador no necesita (ni puede) destruir objetos manualmente. Opcionalmente, antes de ser recolectado, la JVM invoca el método finalize() del objeto, aunque su uso está desaconsejado desde Java 9.

Java
public class CicloVidaDemo {
    public static void main(String[] args) {
        // 1. Creación
        Producto p = new Producto("Monitor", 299.99, 50);

        // 2. Uso
        p.vender(5);
        System.out.println(p);

        // 3. Inaccesibilidad
        p = null;  // La referencia se pierde → el objeto es elegible para GC

        // 4. Sugerir recolección (la JVM decide cuándo ejecutarla)
        System.gc();
    }
}
💡 Buena práctica: No llames a System.gc() en código de producción. La JVM optimiza la recolección de basura de forma automática y una llamada explícita puede degradar el rendimiento. Confía en el GC.

⚖️ Igualdad vs. identidad: == y equals()

Uno de los errores más frecuentes entre programadores Java principiantes es confundir la igualdad (mismo contenido) con la identidad (mismo objeto en memoria). Java proporciona dos mecanismos diferentes para cada caso:

Mecanismo Compara Uso típico
== Referencias (direcciones de memoria) Verificar si dos variables apuntan al mismo objeto
equals() Contenido lógico (si se sobrescribe) Verificar si dos objetos son equivalentes en valor
Java
String s1 = new String("Hola");
String s2 = new String("Hola");

System.out.println(s1 == s2);      // false → son objetos distintos en memoria
System.out.println(s1.equals(s2)); // true  → mismo contenido "Hola"

// Caso especial: literales String (pool de cadenas)
String s3 = "Hola";
String s4 = "Hola";
System.out.println(s3 == s4);      // true → la JVM reutiliza el mismo literal

Para que equals() funcione correctamente en tus propias clases, debes sobrescribirlo (junto con hashCode()). La implementación por defecto heredada de Object simplemente compara referencias, comportamiento idéntico a ==.

Java
public class Producto {
    private String nombre;
    private double precio;

    // ... constructor, getters, setters ...

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;                    // Misma referencia
        if (obj == null || getClass() != obj.getClass()) return false;
        Producto otro = (Producto) obj;
        return Double.compare(otro.precio, precio) == 0
            && Objects.equals(nombre, otro.nombre);
    }

    @Override
    public int hashCode() {
        return Objects.hash(nombre, precio);
    }
}

🛒 Ejemplo integrador: sistema de productos

Veamos un ejemplo completo que reúne todos los conceptos vistos: creación de objetos, atributos, métodos, referencias, toString() y equals(). Simularemos un pequeño sistema de gestión de productos de un comercio electrónico:

Java — Producto.java
import java.util.Objects;

public class Producto {
    private String codigo;
    private String nombre;
    private double precio;
    private int stock;

    public Producto(String codigo, String nombre, double precio, int stock) {
        this.codigo = codigo;
        this.nombre = nombre;
        this.precio = precio;
        this.stock  = stock;
    }

    // --- Getters ---
    public String getCodigo()  { return codigo; }
    public String getNombre()  { return nombre; }
    public double getPrecio()  { return precio; }
    public int    getStock()   { return stock; }

    // --- Lógica de negocio ---
    public boolean hayStock() {
        return stock > 0;
    }

    public boolean vender(int cantidad) {
        if (cantidad <= 0 || cantidad > stock) return false;
        stock -= cantidad;
        return true;
    }

    public void reponer(int cantidad) {
        if (cantidad > 0) stock += cantidad;
    }

    public double valorInventario() {
        return precio * stock;
    }

    // --- equals, hashCode, toString ---
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Producto otro = (Producto) obj;
        return Objects.equals(codigo, otro.codigo);
    }

    @Override
    public int hashCode() {
        return Objects.hash(codigo);
    }

    @Override
    public String toString() {
        return String.format("[%s] %s — %.2f€ (stock: %d)",
                             codigo, nombre, precio, stock);
    }
}
Java — TiendaDemo.java
public class TiendaDemo {
    public static void main(String[] args) {
        // Crear objetos
        Producto teclado = new Producto("TEC-001", "Teclado mecánico", 79.99, 30);
        Producto raton   = new Producto("RAT-002", "Ratón ergonómico", 34.50, 100);
        Producto monitor = new Producto("MON-003", "Monitor 27\" 4K",  349.00, 15);

        // Usar métodos
        System.out.println("=== INVENTARIO INICIAL ===");
        System.out.println(teclado);
        System.out.println(raton);
        System.out.println(monitor);

        // Vender productos
        teclado.vender(5);
        raton.vender(20);
        monitor.vender(2);

        System.out.println("\n=== TRAS VENTAS ===");
        System.out.println(teclado);  // stock: 25
        System.out.println(raton);    // stock: 80
        System.out.println(monitor);  // stock: 13

        // Valor total del inventario
        double total = teclado.valorInventario()
                     + raton.valorInventario()
                     + monitor.valorInventario();
        System.out.printf("\nValor total del inventario: %.2f€%n", total);

        // Comparar objetos
        Producto copia = new Producto("TEC-001", "Teclado mecánico", 79.99, 30);
        System.out.println("\n¿teclado == copia?     " + (teclado == copia));      // false
        System.out.println("¿teclado.equals(copia)? " + teclado.equals(copia));    // true
    }
}

🐛 Errores frecuentes al trabajar con objetos

A continuación se presentan los errores más habituales que cometen los programadores al trabajar con objetos en Java, junto con su causa y solución:

Error Causa Solución
NullPointerException Usar un objeto que nunca se instanció o cuya referencia es null Siempre instanciar con new antes de usar; comprobar null cuando sea necesario
Comparar con == en vez de equals() Se comparan direcciones de memoria, no el contenido Usar equals() para comparar valores; sobrescribirlo en clases propias
Modificar objeto compartido sin querer Varias variables apuntan al mismo objeto en el heap Crear copias defensivas (constructor de copia o clone())
No sobrescribir toString() Al imprimir el objeto aparece Clase@hashcode Implementar toString() con información legible
Atributos públicos sin protección Cualquier código puede establecer valores inválidos Declarar atributos private y exponer setters con validación

✏️ Ejercicios prácticos

Ejercicio 1 — Crear la clase Libro

Crea una clase Libro con atributos titulo (String), autor (String), paginas (int) y precio (double). Incluye un constructor con todos los parámetros, getters, toString() y un método aplicarDescuento(double porcentaje) que reduzca el precio. En el main, crea dos libros, aplica un 15% de descuento al primero e imprime ambos.

Ver solución
Java
public class Libro {
    private String titulo;
    private String autor;
    private int paginas;
    private double precio;

    public Libro(String titulo, String autor, int paginas, double precio) {
        this.titulo  = titulo;
        this.autor   = autor;
        this.paginas = paginas;
        this.precio  = precio;
    }

    public String getTitulo()  { return titulo; }
    public String getAutor()   { return autor; }
    public int    getPaginas() { return paginas; }
    public double getPrecio()  { return precio; }

    public void aplicarDescuento(double porcentaje) {
        if (porcentaje > 0 && porcentaje < 100) {
            precio -= precio * porcentaje / 100;
        }
    }

    @Override
    public String toString() {
        return String.format("\"%s\" de %s — %d págs. — %.2f€",
                             titulo, autor, paginas, precio);
    }

    public static void main(String[] args) {
        Libro libro1 = new Libro("El Quijote", "Cervantes", 863, 24.90);
        Libro libro2 = new Libro("1984", "George Orwell", 326, 15.50);

        libro1.aplicarDescuento(15);

        System.out.println(libro1); // "El Quijote" de Cervantes — 863 págs. — 21.17€
        System.out.println(libro2); // "1984" de George Orwell — 326 págs. — 15.50€
    }
}

Ejercicio 2 — Referencias y aliasing

Sin ejecutar el código, predice la salida del siguiente programa. Después, compruébalo en tu IDE:

Java
Producto a = new Producto("X01", "USB", 9.99, 200);
Producto b = a;
Producto c = new Producto("X01", "USB", 9.99, 200);

b.vender(50);
System.out.println(a.getStock());  // ¿?
System.out.println(c.getStock()); // ¿?
System.out.println(a == b);       // ¿?
System.out.println(a == c);       // ¿?
System.out.println(a.equals(c));  // ¿?
Ver solución
Salida
150     // b.vender(50) afecta a 'a' porque apuntan al MISMO objeto
200     // 'c' es un objeto independiente, no se ve afectado
true    // 'a' y 'b' son la misma referencia
false   // 'a' y 'c' son objetos distintos en memoria
true    // equals() compara por código ("X01") → son equivalentes

Ejercicio 3 — Sistema de gestión de alumnos

Crea la clase Alumno con atributos nombre, nota1, nota2 y nota3 (todos double). Incluye: un constructor, un método calcularMedia(), un método estaAprobado() (media ≥ 5.0) y toString(). En el main, crea un array de 3 alumnos, calcula la media de cada uno e indica cuántos aprobaron.

Ver solución
Java
public class Alumno {
    private String nombre;
    private double nota1, nota2, nota3;

    public Alumno(String nombre, double nota1, double nota2, double nota3) {
        this.nombre = nombre;
        this.nota1 = nota1;
        this.nota2 = nota2;
        this.nota3 = nota3;
    }

    public double calcularMedia() {
        return (nota1 + nota2 + nota3) / 3.0;
    }

    public boolean estaAprobado() {
        return calcularMedia() >= 5.0;
    }

    @Override
    public String toString() {
        return String.format("%s → Media: %.2f → %s",
            nombre, calcularMedia(), estaAprobado() ? "APROBADO" : "SUSPENSO");
    }

    public static void main(String[] args) {
        Alumno[] alumnos = {
            new Alumno("María López",  7.5, 8.0, 6.5),
            new Alumno("Carlos Ruiz",  4.0, 3.5, 5.0),
            new Alumno("Lucía Martín", 9.0, 8.5, 9.5)
        };

        int aprobados = 0;
        for (Alumno a : alumnos) {
            System.out.println(a);
            if (a.estaAprobado()) aprobados++;
        }
        System.out.printf("%nTotal aprobados: %d de %d%n", aprobados, alumnos.length);
    }
}

Ejercicio 4 — Constructor de copia

Añade a la clase Producto del ejemplo integrador un constructor de copia que reciba otro Producto y cree una copia independiente. Demuestra en el main que modificar la copia no afecta al original.

Ver solución
Java
// Añadir a la clase Producto:
public Producto(Producto otro) {
    this.codigo = otro.codigo;
    this.nombre = otro.nombre;
    this.precio = otro.precio;
    this.stock  = otro.stock;
}

// En el main:
Producto original = new Producto("TEC-001", "Teclado", 79.99, 30);
Producto copia    = new Producto(original);  // Constructor de copia

copia.vender(10);

System.out.println("Original: " + original.getStock()); // 30 (no afectado)
System.out.println("Copia:    " + copia.getStock());    // 20

❓ Preguntas frecuentes sobre El Objeto en POO: qué es y cómo se crea en Java

Las dudas más comunes respondidas de forma clara y directa.

Un objeto en Java es una instancia concreta de una clase. Contiene un estado (valores de sus atributos), un comportamiento (métodos que puede ejecutar) y una identidad única (referencia en memoria). Se crea mediante el operador new seguido del constructor de la clase.
Una clase es una plantilla o molde que define atributos y métodos. Un objeto es una instancia concreta de esa clase, con valores específicos en sus atributos. Por ejemplo, la clase Coche define que todo coche tiene color y velocidad, mientras que un objeto concreto podría ser un coche rojo a 60 km/h.
El operador new reserva memoria en el heap para un nuevo objeto, invoca el constructor de la clase para inicializar sus atributos y devuelve una referencia (dirección de memoria) al objeto recién creado. Sin new no se puede crear un objeto en Java (salvo excepciones como literales String).
Cuando ninguna variable referencia a un objeto, este se convierte en elegible para el recolector de basura (Garbage Collector). El GC libera la memoria del heap automáticamente en un momento indeterminado. No es necesario destruir objetos manualmente en Java, a diferencia de lenguajes como C++.
El operador == compara referencias: devuelve true solo si ambas variables apuntan al mismo objeto en memoria. El método equals() compara el contenido lógico de los objetos (si la clase lo sobrescribe). Para comparar valores de objetos como String o Integer siempre se debe usar equals(), no ==.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre El Objeto en POO: qué es y cómo se crea en Java? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!