Declaración de una clase en Java

📅 Actualizado en febrero 2026 ✍️ Ángel López ⏱️ 14 min de lectura ✓ Nivel principiante

📦 ¿Qué es una declaración de clase?

En Java, todo programa se construye a partir de clases. Una declaración de clase es la definición formal que establece qué datos almacena un tipo de objeto (sus campos o atributos) y qué operaciones puede realizar (sus métodos). Se trata del bloque de construcción fundamental de la programación orientada a objetos en Java.

Cuando se escribe una declaración de clase, se está creando un nuevo tipo de dato en el lenguaje. A partir de ese tipo, se pueden instanciar tantos objetos como se necesiten mediante el operador new. Cada objeto tendrá su propia copia de los campos de instancia, pero compartirá la definición de los métodos.

💡
Concepto clave: Una clase es a un objeto lo que un plano arquitectónico es a un edificio. El plano describe la estructura; cada edificio construido a partir de él es una instancia concreta con sus propias características (color de fachada, número de planta, etc.).

Veamos una clase sencilla llamada Publicacion que podríamos utilizar para almacenar los datos de una colección bibliográfica:

public class Publicacion {

    // Campos (atributos)
    int idPublicacion;
    String titulo;
    String autor;
}

Con esta declaración, Publicacion se convierte en un tipo válido en Java. Ahora se pueden crear referencias y objetos de ese tipo:

Publicacion miLibro;                            // Referencia (aún sin objeto)
miLibro = new Publicacion();                    // Instanciación del objeto
miLibro.titulo = "El Quijote";                  // Acceso al campo
System.out.println(miLibro.titulo);              // El Quijote

📝 Sintaxis básica de una clase

La estructura general de una declaración de clase en Java sigue este patrón:

// Estructura general de una clase en Java
[modificador_acceso] [modificadores] class NombreClase [extends SuperClase] [implements Interfaz1, Interfaz2] {

    // 1. Campos (variables de instancia y de clase)
    // 2. Constructores
    // 3. Métodos
    // 4. Clases internas (opcional)
}

Cada componente tiene un propósito específico:

Componente Obligatorio Descripción
modificador_acceso No public, default (sin modificador). Determina la visibilidad de la clase.
modificadores No abstract, final, strictfp. Modifican el comportamiento de la clase.
class NombreClase Palabra clave class seguida del nombre. Debe ser un identificador válido y empezar por mayúscula.
extends SuperClase No Indica de qué clase hereda. Si se omite, hereda implícitamente de Object.
implements Interfaces No Lista de interfaces que la clase se compromete a implementar.
Cuerpo { } Contiene campos, constructores, métodos y clases internas.

▶️ Ejemplo mínimo

La clase más simple posible en Java contiene solo la palabra clave class, un nombre y un cuerpo vacío:

class Vacia {
    // Clase válida aunque sin contenido
}

Aunque legal, una clase vacía no tiene utilidad práctica. En los siguientes apartados se detallan los elementos que la convierten en una herramienta útil.

🗂️ Campos (atributos) de una clase

Los campos (fields), también llamados variables de instancia o atributos, representan el estado de cada objeto. Se declaran dentro del cuerpo de la clase, fuera de cualquier método.

🔹 Declaración de un campo

[modificador_acceso] [modificadores] tipo nombreCampo [= valorInicial];

🔹 Ejemplo con varios campos

public class Vehiculo {

    // Campos de instancia
    private String marca;
    private String modelo;
    private int anio;
    private double velocidadActual = 0.0;   // Valor inicial explícito
    private boolean encendido = false;      // Valor inicial explícito
}

🔹 Valores por defecto de los campos

Si no se asigna un valor explícito, Java inicializa los campos de instancia con valores predeterminados:

Tipo Valor por defecto
byte, short, int, long0
float, double0.0
char'\u0000'
booleanfalse
Referencias a objetos (String, arrays, etc.)null
⚠️
Atención: Las variables locales (declaradas dentro de métodos) no reciben valor por defecto. Si se intenta leer una variable local sin inicializar, el compilador genera un error. Esta regla solo aplica a campos de instancia y de clase.

⚙️ Métodos de una clase

Los métodos definen el comportamiento de los objetos. Se declaran dentro de la clase y pueden acceder a todos los campos del objeto (incluyendo los privados) mediante la referencia implícita this.

▶️ Firma de un método

[modificador_acceso] [modificadores] tipoRetorno nombreMetodo([parámetros]) [throws excepciones] {
    // Cuerpo del método
}

▶️ Clase con campos y métodos

public class Rectangulo {

    private double ancho;
    private double alto;

    public Rectangulo(double ancho, double alto) {
        this.ancho = ancho;
        this.alto = alto;
    }

    public double calcularArea() {
        return ancho * alto;
    }

    public double calcularPerimetro() {
        return 2 * (ancho + alto);
    }

    public String describir() {
        return "Rectángulo " + ancho + "x" + alto +
               " | Área: " + calcularArea() +
               " | Perímetro: " + calcularPerimetro();
    }
}
Buena práctica: Nombra los métodos con verbos que describan la acción que realizan: calcularArea(), obtenerNombre(), estaActivo(). Esto mejora la legibilidad del código.

🔧 Constructores

Un constructor es un bloque de código especial que se ejecuta automáticamente cuando se crea un objeto con new. Su misión es inicializar el estado del objeto, asignando valores a los campos de instancia.

🔹 Reglas de los constructores

Un constructor se distingue de un método normal por tres características: su nombre es idéntico al de la clase, no tiene tipo de retorno (ni siquiera void) y se invoca exclusivamente a través del operador new.

🔹 Constructor por defecto

Si no se declara ningún constructor, el compilador genera uno automáticamente sin parámetros que inicializa los campos con sus valores por defecto. Sin embargo, en cuanto se declara cualquier constructor (con o sin parámetros), el compilador deja de proporcionar el constructor por defecto.

🔹 Sobrecarga de constructores

Es habitual declarar varios constructores con distintas combinaciones de parámetros para ofrecer flexibilidad al instanciar objetos:

public class Libro {

    private String titulo;
    private String autor;
    private int paginas;

    // Constructor completo
    public Libro(String titulo, String autor, int paginas) {
        this.titulo = titulo;
        this.autor = autor;
        this.paginas = paginas;
    }

    // Constructor parcial (delega en el completo)
    public Libro(String titulo, String autor) {
        this(titulo, autor, 0);   // Llama al constructor de 3 parámetros
    }

    // Constructor sin parámetros
    public Libro() {
        this("Sin título", "Desconocido", 0);
    }
}
📘
Nota: La llamada this(...) a otro constructor de la misma clase debe ser la primera instrucción del constructor. No se puede colocar después de otras sentencias.

⚡ Miembros estáticos (static)

Los miembros declarados con la palabra clave static pertenecen a la clase en su conjunto y no a ninguna instancia individual. Existen en memoria independientemente de que se hayan creado objetos o no.

🔹 Campos estáticos

Un campo estático es compartido por todas las instancias de la clase. Se utiliza comúnmente para contadores, constantes de configuración o valores que no varían entre objetos.

public class Empleado {

    private static int contadorEmpleados = 0;   // Compartido por todos
    private int id;
    private String nombre;

    public Empleado(String nombre) {
        contadorEmpleados++;
        this.id = contadorEmpleados;
        this.nombre = nombre;
    }

    public static int getTotalEmpleados() {
        return contadorEmpleados;
    }
}

// Uso:
Empleado e1 = new Empleado("Ana");      // contadorEmpleados = 1
Empleado e2 = new Empleado("Carlos");   // contadorEmpleados = 2
System.out.println(Empleado.getTotalEmpleados());  // 2

🔹 Constantes con static final

La combinación static final declara una constante de clase: un valor que no cambia y es compartido por todas las instancias. Por convención, se escribe en MAYÚSCULAS con guiones bajos:

public class Configuracion {

    public static final int MAX_INTENTOS = 3;
    public static final double IVA = 0.21;
    public static final String VERSION = "2.5.1";
}

// Acceso directo por el nombre de la clase:
System.out.println(Configuracion.MAX_INTENTOS);  // 3

📐 Convenciones de nomenclatura

Java tiene convenciones de nomenclatura ampliamente aceptadas que mejoran la legibilidad del código y facilitan la colaboración entre desarrolladores:

Elemento Convención Ejemplo
Clase PascalCase (empieza con mayúscula, sustantivo) CuentaBancaria, Vehiculo
Campo / Variable camelCase (empieza con minúscula) saldoActual, nombreCompleto
Método camelCase (verbo como primera palabra) calcularTotal(), getNombre()
Constante MAYUSCULAS_CON_GUIONES MAX_VALOR, PI
Paquete todo en minúsculas, dominio invertido com.empresa.proyecto
Buena práctica: Si la clase es pública, el nombre del archivo .java debe coincidir exactamente con el nombre de la clase, incluyendo mayúsculas: CuentaBancaria.java contiene public class CuentaBancaria.

🏗️ Ejemplo completo integrador

El siguiente programa simula un sistema de gestión de una biblioteca. Integra todos los conceptos: campos con encapsulamiento, constructores sobrecargados, métodos de instancia y estáticos, y constantes.

public class Publicacion {

    // Constante de clase
    public static final int MAX_TITULO = 200;

    // Campo estático: contador global
    private static int totalPublicaciones = 0;

    // Campos de instancia
    private int id;
    private String titulo;
    private String autor;
    private int anioPublicacion;
    private boolean disponible;

    // Constructor completo
    public Publicacion(String titulo, String autor, int anioPublicacion) {
        if (titulo == null || titulo.isBlank()) {
            throw new IllegalArgumentException("El título no puede estar vacío");
        }
        if (titulo.length() > MAX_TITULO) {
            throw new IllegalArgumentException("Título demasiado largo");
        }
        totalPublicaciones++;
        this.id = totalPublicaciones;
        this.titulo = titulo.trim();
        this.autor = (autor != null) ? autor.trim() : "Anónimo";
        this.anioPublicacion = anioPublicacion;
        this.disponible = true;
    }

    // Constructor parcial
    public Publicacion(String titulo, String autor) {
        this(titulo, autor, 0);
    }

    // Getters
    public int     getId()               { return id; }
    public String  getTitulo()           { return titulo; }
    public String  getAutor()            { return autor; }
    public int     getAnioPublicacion()  { return anioPublicacion; }
    public boolean isDisponible()       { return disponible; }

    // Métodos de negocio
    public void prestar() {
        if (!disponible) {
            System.out.println("'" + titulo + "' ya está prestado.");
            return;
        }
        disponible = false;
        System.out.println("Prestado: " + titulo);
    }

    public void devolver() {
        disponible = true;
        System.out.println("Devuelto: " + titulo);
    }

    // Método estático
    public static int getTotalPublicaciones() {
        return totalPublicaciones;
    }

    @Override
    public String toString() {
        return "[#" + id + "] " + titulo +
               " (" + autor + ", " + anioPublicacion + ")" +
               (disponible ? " - Disponible" : " - Prestado");
    }
}
public class Biblioteca {

    public static void main(String[] args) {

        Publicacion p1 = new Publicacion("El Quijote", "Cervantes", 1605);
        Publicacion p2 = new Publicacion("Effective Java", "Joshua Bloch", 2018);
        Publicacion p3 = new Publicacion("Clean Code", "Robert C. Martin");

        System.out.println("=== Catálogo ===");
        System.out.println(p1);
        System.out.println(p2);
        System.out.println(p3);

        System.out.println("\nTotal publicaciones: " + Publicacion.getTotalPublicaciones());

        p1.prestar();
        p1.prestar();   // Intento duplicado
        p1.devolver();
    }
}

// Salida esperada:
// === Catálogo ===
// [#1] El Quijote (Cervantes, 1605) - Disponible
// [#2] Effective Java (Joshua Bloch, 2018) - Disponible
// [#3] Clean Code (Robert C. Martin, 0) - Disponible
//
// Total publicaciones: 3
// Prestado: El Quijote
// 'El Quijote' ya está prestado.
// Devuelto: El Quijote

🐛 Errores frecuentes

⚠️
Error 1: Poner tipo de retorno en el constructor
Si se añade un tipo de retorno (incluso void) a lo que se pretendía que fuera un constructor, Java lo interpreta como un método normal y no se ejecutará al crear el objeto con new.
// ❌ INCORRECTO — esto es un método, NO un constructor
public void Persona(String nombre) {
    this.nombre = nombre;
}

// ✅ CORRECTO — sin tipo de retorno
public Persona(String nombre) {
    this.nombre = nombre;
}
⚠️
Error 2: Declarar campos como públicos
Exponer los campos directamente rompe el encapsulamiento. Si más adelante se necesita validar o transformar el dato, habrá que cambiar todo el código que accede al campo.
// ❌ INCORRECTO
public String nombre;

// ✅ CORRECTO
private String nombre;
public String getNombre() { return nombre; }
⚠️
Error 3: Archivo y clase con nombres distintos
Si la clase es public, el archivo debe llamarse exactamente igual (con la misma capitalización). public class MiClase debe estar en MiClase.java, no en miclase.java ni MI_CLASE.java.
⚠️
Error 4: Olvidar que sin constructor explícito el compilador genera uno
Si se añade un constructor con parámetros y se intenta crear un objeto sin argumentos (new MiClase()), el código no compilará, porque el constructor por defecto ya no existe. Hay que declarar explícitamente el constructor sin parámetros si se desea mantener ambas opciones.

📝 Ejercicios prácticos

Ejercicio 1: Comprensión — ¿Qué imprime este código?

Analiza el siguiente código y determina la salida por consola sin ejecutarlo:

public class Contador {
    private static int total = 0;
    private int id;

    public Contador() {
        total++;
        this.id = total;
    }

    public static void main(String[] args) {
        Contador a = new Contador();
        Contador b = new Contador();
        Contador c = new Contador();
        System.out.println(a.id + " " + b.id + " " + c.id);
        System.out.println("Total: " + total);
    }
}

Ejercicio 2: Aplicación — Clase Producto

Escribe una clase Producto con los siguientes requisitos:

  • Campos privados: nombre (String), precio (double), stock (int).
  • Constructor que valide: nombre no vacío, precio >= 0, stock >= 0.
  • Método vender(int cantidad) que disminuya el stock si hay suficiente.
  • Método toString() descriptivo.

Ejercicio 3: Diseño — Clase Asignatura con constructores sobrecargados

Diseña una clase Asignatura con campos nombre (String), creditos (int) y profesor (String). Debe tener tres constructores: uno completo (los tres campos), uno parcial (nombre y créditos, con profesor = "Por asignar") y uno mínimo (solo nombre, con créditos = 6 y profesor = "Por asignar"). Usa this(...) para delegar entre constructores.

❓ Preguntas frecuentes sobre Declaración de una clase en Java

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

Una clase es la plantilla o molde que define la estructura (campos) y el comportamiento (métodos) de un tipo de dato. Un objeto es una instancia concreta de esa clase, creada en memoria con el operador new. Por ejemplo, la clase Coche define qué atributos tiene un coche (marca, modelo, velocidad), y cada objeto es un coche concreto con sus propios valores.
Sí. Java permite la sobrecarga de constructores: una clase puede tener varios constructores siempre que difieran en el número o tipo de parámetros. Esto permite crear objetos de distintas formas según la información disponible en el momento de la instanciación.
Si no se declara ningún constructor, el compilador de Java genera automáticamente un constructor por defecto sin parámetros que inicializa los campos con sus valores predeterminados (0 para numéricos, false para boolean, null para referencias). Sin embargo, si se declara al menos un constructor con parámetros, el compilador ya no genera el constructor por defecto.
Un campo de instancia pertenece a cada objeto individual: cada instancia tiene su propia copia con su propio valor. Un campo estático (declarado con static) pertenece a la clase en su conjunto y es compartido por todas las instancias. Se utiliza para valores comunes, como contadores de objetos creados o constantes de configuración.
Si la clase se declara como public, el nombre del archivo .java debe coincidir exactamente con el nombre de la clase, incluyendo mayúsculas y minúsculas. Si la clase no es pública, el archivo puede tener cualquier nombre, aunque por convención se recomienda que coincidan para facilitar la localización del código.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Declaración de una clase en Java? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

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