3. Estructura de un programa Java
Ficha de la sección
| Campo | Valor |
|---|---|
| Unidad de Programación | UD1 — Fundamentos de Programación |
| Resultado de Aprendizaje | RA1 — Reconoce la estructura de un programa informático, identificando y relacionando los elementos propios del lenguaje de programación utilizado |
| Duración orientativa | Aproximadamente 4 de las 28 horas totales de UD1 |
| Criterios de Evaluación implicados | CE 1.1 (Se han identificado los bloques que componen la estructura de un programa informático) como criterio principal, y CE 1.9 (Se han introducido comentarios en el código) |
| Encaja en el roadmap | Es el momento en el que la teoría de la Sección 1 (programa, algoritmo, instrucción) y las herramientas de la Sección 2 (IntelliJ, Maven) se encuentran por primera vez con sintaxis Java real. A partir de aquí, todas las unidades del curso dan por hecho que sabes leer y montar el esqueleto de cualquier clase Java |
Antes de empezar
Ya tienes el taller montado (IntelliJ) y el motor conectado (JDK 25 vía Maven). Toca abrir el capó y mirar, pieza a pieza, qué hay dentro de un programa Java. Y aquí viene la buena noticia: no vas a aprender nada nuevo desde cero, vas a ponerle sintaxis a algo que ya entiendes.
¿Recuerdas la jerarquía de la Sección 1? Programa → Algoritmo → Instrucción, como un recetario, sus recetas y los pasos de cada receta. Pues bien: en Java, esa misma jerarquía tiene nombre y apellido.
flowchart TB
subgraph CLASS["class HolaMundo { } — tu PROGRAMA (el contenedor obligatorio)"]
direction TB
subgraph MAIN["public static void main(String[] args) { } — tu ALGORITMO principal (la puerta de entrada)"]
direction TB
L1["Instrucción: System.out.println(...);"]
L2["Instrucción: System.out.println(...);"]
L3["Instrucción: ..."]
end
end
style CLASS fill:#e3f2fd,stroke:#1565c0
style MAIN fill:#e8f5e9,stroke:#2e7d32
La clase es tu programa (el contenedor obligatorio). El método main es, de momento, tu algoritmo principal (la puerta de entrada por la que todo empieza). Y cada línea de código dentro de él es una instrucción. Vamos a diseccionar cada pieza.
3.1. La clase como contenedor obligatorio
En Java, todo el código que escribas (con una única excepción que veremos en el apartado 3.3) tiene que vivir dentro de una clase. No existe la posibilidad de escribir instrucciones "sueltas" a nivel del fichero, como sí ocurre en otros lenguajes. La clase es el envoltorio obligatorio: nada se ejecuta sin estar dentro de una.
| Palabra | Qué significa | ¿Se puede cambiar? |
|---|---|---|
public |
Modificador de acceso: esta clase es visible desde cualquier otro fichero o paquete del proyecto | Sí existen otras opciones (las verás en profundidad en UD4), pero por ahora usaremos siempre public |
class |
Palabra reservada del lenguaje: declara que lo que sigue es una clase | No, es una palabra fija del lenguaje |
HolaMundo |
El nombre que tú eliges para tu clase | Sí, lo eliges tú, pero con una regla estricta (ver aviso siguiente) |
{ } |
Delimitan el cuerpo de la clase: todo lo que "vive dentro" de ella | Las llaves son obligatorias; su contenido, no |
Regla estricta que causa muchos primeros errores. Si una clase se declara
public, su nombre debe coincidir exactamente (mayúsculas incluidas) con el nombre del fichero que la contiene. Es decir, la clasepublic class HolaMundosolo puede vivir en un fichero llamadoHolaMundo.java. Si el fichero se llamaraholamundo.javaoHola_Mundo.java, el compilador se negaría a compilar. No es una sugerencia de estilo: es una exigencia del compilador.
3.2. El método main: el punto de entrada del programa
Cuando ejecutas un programa Java (con mvn exec:java, con Shift + F10 en IntelliJ, o directamente con el comando java), la JVM no empieza a leer tu clase de arriba abajo como si fuera una novela. Busca, de forma muy concreta, un método con una firma exacta: main. Si no lo encuentra, no hay programa que ejecutar.
flowchart LR
JVM["La JVM arranca\ny busca..."] --> SEARCH{"¿Existe un método\npublic static void main(String[] args)?"}
SEARCH -->|Sí| RUN["Empieza a ejecutar\nel programa desde ahí"]
SEARCH -->|No| ERROR["Error:\n'Main method not found'"]
style JVM fill:#1565c0,color:#fff,stroke:#0d47a1
style RUN fill:#2e7d32,color:#fff,stroke:#1b5e20
style ERROR fill:#b71c1c,color:#fff,stroke:#7f0000
Vamos a diseccionar su firma completa, palabra por palabra, porque cada una está ahí por una razón concreta (aunque algunas las entenderás del todo más adelante):
| Palabra | Qué significa | ¿Por qué está ahí? |
|---|---|---|
public |
El método debe ser accesible desde fuera de la clase | Si fuera private, la JVM no podría "verlo" ni llamarlo desde fuera |
static |
El método pertenece a la clase en sí misma, no a un objeto creado a partir de ella | La JVM tiene que poder llamarlo antes de que exista ningún objeto de tu clase. Profundizaremos en static en UD4 |
void |
El método no devuelve ningún valor | El programa simplemente se ejecuta y termina; no "retorna" un resultado a nadie |
main |
El nombre exacto y fijo que la JVM busca como punto de entrada | Es un contrato del lenguaje: si lo llamas Main, principal o cualquier otra cosa, la JVM no lo encontrará |
String[] args |
Un array de textos con los argumentos que se pasen al ejecutar el programa desde la línea de comandos | Lo usarás más adelante; de momento puede quedarse vacío sin ningún problema |
Nota para el aula. No memorices estas palabras como un conjuro mágico.
public static void main(String[] args)no es una fórmula que "hay que poner sí o sí sin preguntar": es una firma con significado propio, palabra por palabra, y en unas semanas (cuando lleguemos a UD4 y entiendasstatica fondo, o a UD2 cuando trabajes con arrays) todas las piezas encajarán del todo. Por ahora, con la tabla anterior tienes más que suficiente para defenderte con soltura.
3.3. Unnamed classes e instance main methods (Java 25, estables)
Aquí viene una de las novedades más interesantes de Java moderno, y también la única excepción a la regla de "todo vive dentro de una clase" que hemos visto en el punto 3.1.
Desde hace unas versiones, Java ha ido incorporando (primero como funcionalidad de vista previa, y ya estabilizada en Java 25) una forma simplificada de escribir un primer programa, pensada explícitamente para quitar barreras de entrada a quien empieza a programar. En vez de exigir clase pública, static y toda la ceremonia que acabas de ver, te permite escribir directamente esto:
¿Qué ha pasado con la clase? No ha desaparecido: el compilador genera por debajo, de forma automática, una clase sin nombre que envuelve este código. Es decir, la regla de "todo vive dentro de una clase" se sigue cumpliendo, simplemente ya no tienes que escribirla tú a mano.
| Forma clásica | Forma simplificada (Java 25) | |
|---|---|---|
| Palabras clave necesarias | public class NombreClase, y static en el main |
Ninguna: solo void main() { } |
| ¿El nombre de la clase debe coincidir con el fichero? | Sí, siempre | No aplica: el compilador crea una clase sin nombre |
¿Se puede declarar package? |
Sí, y lo usaremos siempre en este curso | No: las unnamed classes viven en el paquete sin nombre |
| ¿Cuándo la usaremos en este módulo? | Siempre que trabajemos dentro de un proyecto Maven, es decir, casi siempre | Solo como apoyo puntual para entender qué simplifica y por qué |
| Pensada para... | Aplicaciones reales, con varias clases organizadas en paquetes | Quien empieza a programar, ejemplos de una sola clase, scripts rápidos de una sesión |
Dato clave y decisión pedagógica de este curso. En este módulo trabajaremos siempre en proyectos Maven, con paquetes (
dam.programacion.udX), tal y como viste en la Sección 2. Como las unnamed classes no admitenpackage, la forma simplificada no encaja bien con esa forma de trabajar profesional que queremos que interiorices desde ya. Por eso usaremos la forma clásica (public class+static) como estándar durante todo el curso. Aun así, era importante que conocieras esta forma simplificada por dos motivos: la vas a encontrar en tutoriales y documentación moderna, y te ayuda a entender qué hace realmente cada palabra de la forma clásica, viendo qué ocurre cuando se quitan.
3.4. Salida por consola: println, printf y print
Para que un programa sirva de algo, necesita comunicarse contigo. La forma más básica es escribir texto en la consola, y Java te da tres métodos para hacerlo, cada uno con un matiz distinto:
| Método | ¿Salta de línea al terminar? | Cuándo lo usarás |
|---|---|---|
System.out.println(...) |
Sí, automáticamente | La opción por defecto: mostrar un valor y pasar a la siguiente línea |
System.out.print(...) |
No | Cuando quieres que la siguiente instrucción continúe escribiendo en la misma línea |
System.out.printf(...) |
No, salvo que incluyas %n explícitamente |
Cuando necesitas dar formato preciso al texto (decimales, anchura de columnas...). Le sacaremos todo el partido en UD5 |
Dato clave.
%nenprintfrepresenta un salto de línea "independiente del sistema operativo" (en Windows es distinto internamente que en Linux/macOS, y%nse adapta solo). Es preferible a escribir\na mano cuando usasprintf, aunque\ntambién funciona y lo verás con frecuencia.
3.5. Sensibilidad a mayúsculas, punto y coma, y bloques { }
Java es, en esto, un lenguaje extremadamente estricto y nada tolerante con la ambigüedad, exactamente como ya anticipamos en la Sección 1 al hablar de qué significa programar. Tres reglas que no admiten excepciones:
- Java distingue mayúsculas de minúsculas (case-sensitive).
System,systemySYSTEMson tres identificadores completamente distintos para el compilador. No hay margen de interpretación. - Cada instrucción termina en punto y coma
;. El punto y coma le dice al compilador "aquí termina esta orden". Sin él, el compilador no sabe dónde acaba una instrucción y dónde empieza la siguiente. - Los bloques de código se delimitan con llaves
{ }. Toda clase y todo método necesitan sus llaves de apertura y cierre. Un desajuste en el número de llaves suele arrastrar errores de compilación confusos a líneas que, en realidad, están bien escritas.
| Error típico | Ejemplo | Por qué falla |
|---|---|---|
| Olvidar el punto y coma | System.out.println("Hola") sin ; al final |
El compilador no sabe dónde termina la instrucción |
| Confundir mayúsculas y minúsculas | Escribir system.out.println(...) en vez de System.out.println(...) |
system (minúscula) no existe; es un identificador distinto de System |
Llaves { } descuadradas |
Abrir una llave y olvidar cerrarla más adelante | El compilador arrastra el error, a veces señalando una línea muy posterior que en realidad está bien escrita |
| Nombre de clase distinto al del fichero | Clase public class Main guardada en un fichero HolaMundo.java |
El compilador exige que coincidan exactamente cuando la clase es public |
Nota para el aula. El primer día que el compilador te señale un error "en la línea 47" cuando tu error real está en la línea 12 (por una llave
{que te dejaste sin cerrar), vas a dudar de tu cordura. Es de lo más normal del mundo: el compilador interpreta el código según las reglas que le has dado, y si desde la línea 12 "algo queda abierto", arrastra la confusión hasta donde puede. IntelliJ te ayuda mucho aquí resaltando visualmente las llaves que hacen pareja; apóyate en esa ayuda visual sin remordimientos.
3.6. Comentarios: //, /* */ y Javadoc /** */
Los comentarios son texto que escribes en tu código pero que el compilador ignora por completo: no forman parte del programa, son notas para los humanos que lean ese código (incluido tú mismo, dentro de seis meses, cuando ya no recuerdes por qué escribiste algo de una forma concreta).
| Tipo | Sintaxis | Para qué se usa |
|---|---|---|
| De línea | // comentario |
Aclaraciones puntuales y muy cortas |
| De bloque | /* ... */ |
Explicaciones más largas, o para anular temporalmente varias líneas de código |
| Javadoc | /** ... */ |
Documentación oficial de clases y métodos, exportable como HTML con la herramienta javadoc |
Buena práctica desde el primer día. Un comentario útil explica el por qué, no el qué. Comentar
i++; // incrementa i en unoes ruido: cualquiera que sepa Java ya ve quei++incrementai. En cambio, un comentario como// se empieza en 1 y no en 0 porque el primer trimestre del ciclo no se numerasí aporta información que el código, por sí solo, no cuenta. Los comentarios que solo repiten lo obvio envejecen mal: en cuanto el código cambia, el comentario suele quedarse desactualizado y mentir descaradamente sobre lo que el programa hace de verdad.
3.7. Convenciones de nomenclatura Java
Java tiene convenciones de estilo muy asentadas en toda su comunidad, hasta el punto de que IntelliJ te avisará (con un subrayado amarillo) si las rompes. No son caprichos: permiten que cualquier programador Java del mundo, al leer tu código, sepa de un vistazo si algo es una clase, una variable o una constante, sin necesidad de mirar su declaración.
| Convención | Se usa para... | Ejemplos |
|---|---|---|
| PascalCase (cada palabra empieza en mayúscula, incluida la primera) | Nombres de clases | HolaMundo, CuentaBancaria, GestorNotas |
| camelCase (la primera palabra en minúscula, el resto con mayúscula inicial) | Variables y métodos | notaMedia, numeroAlumnos, calcularNotaMedia() |
| UPPER_SNAKE_CASE (todo en mayúsculas, palabras separadas por guion bajo) | Constantes (static final) |
NOTA_MAXIMA, IVA_GENERAL, DIAS_SEMANA |
| minúsculas, sin guiones | Nombres de paquete | dam.programacion.ud1 |
flowchart TD
N["Nombra algo en Java"] --> Q{"¿Qué es?"}
Q -->|Una clase| PC["PascalCase\nHolaMundo"]
Q -->|Una variable o método| CC["camelCase\nnotaMedia"]
Q -->|Una constante| UC["UPPER_SNAKE_CASE\nNOTA_MAXIMA"]
Q -->|Un paquete| PKG["minúsculas.sin.guiones\ndam.programacion.ud1"]
style PC fill:#1565c0,color:#fff,stroke:#0d47a1
style CC fill:#2e7d32,color:#fff,stroke:#1b5e20
style UC fill:#e65100,color:#fff,stroke:#bf360c
style PKG fill:#6a1b9a,color:#fff,stroke:#4a148c
Nota para el aula. Estas convenciones no las inventa cada programador a su gusto: están recogidas en las Java Code Conventions originales y asumidas por toda la comunidad desde hace más de 25 años. Adoptarlas desde tu primera línea de código no es un capricho estético: es lo que hace que tu código "se lea como Java" y que cualquier compañero, o cualquier entrevistador técnico, lo reconozca como código escrito por alguien que sabe lo que hace.
Programa completo: todas las piezas juntas
Vamos a cerrar la sección reuniendo, en un único fichero real, todo lo que hemos visto: paquete, Javadoc, clase, constante con nomenclatura correcta, método main, variable local con nomenclatura correcta, y varias formas de salida por consola.
Resumen de la sección
| Idea clave | En una frase |
|---|---|
| Clase | El contenedor obligatorio de todo el código Java; su nombre debe coincidir con el del fichero si es public |
Método main |
El punto de entrada fijo que la JVM busca para empezar a ejecutar el programa |
| Unnamed classes / instance main | Forma simplificada (Java 25) sin clase explícita ni static; útil para entender, no la usaremos como estándar en este curso |
println / print / printf |
Salida por consola con salto de línea, sin salto de línea, o con formato preciso |
Case sensitivity, ;, { } |
Java no perdona ambigüedades: mayúsculas y minúsculas son distintas, cada instrucción lleva su punto y coma, cada bloque sus llaves |
| Comentarios | // para líneas sueltas, /* */ para bloques, /** */ (Javadoc) para documentación generable |
| Nomenclatura | PascalCase (clases), camelCase (variables y métodos), UPPER_SNAKE_CASE (constantes), minúsculas (paquetes) |
Comprueba lo que has entendido
- Si tienes una clase
public class GestorNotas, ¿cómo se debe llamar obligatoriamente el fichero que la contiene? - ¿Por qué la JVM no podría ejecutar un método
maindeclarado comoprivate? - ¿Qué diferencia real hay entre la forma clásica de
mainy la forma simplificada de unnamed class, y por qué en este curso usaremos casi siempre la clásica? - Clasifica estos tres identificadores según la convención de nomenclatura que les correspondería: una clase para gestionar alumnos, una variable para guardar la nota media, una constante para el número máximo de créditos.
Qué viene ahora
Ya sabes leer y montar el esqueleto completo de cualquier clase Java: contenedor, punto de entrada, salida por consola, comentarios y nomenclatura correcta. En la Sección 4 de UD1 vamos a meternos dentro de esas instrucciones para trabajar con variables y tipos primitivos: los ocho tipos básicos de Java, cómo declararlos e inicializarlos, la inferencia con var, y los literales numéricos modernos como el separador _ o los formatos hexadecimal y binario.