2. Clases y objetos en la API de Java
| Campo | Contenido |
|---|---|
| Unidad | UD3, Programación Orientada a Objetos con la API de Java |
| RA | RA2, Escribe y prueba programas sencillos, reconociendo y aplicando los fundamentos de la programación orientada a objetos |
| CE cubiertos | CE 2.5 (se han escrito llamadas a métodos estáticos), CE 2.7 (se han incorporado y utilizado librerías de objetos) y CE 2.9 (se ha utilizado el entorno integrado de desarrollo) de forma directa; refuerzo de CE 2.2, CE 2.3, CE 2.4, CE 2.6 y CE 2.8 |
En esta sección aprenderás:
- Cómo está organizado el API de Java —miles de clases listas para usar— en módulos, paquetes y clases, y cómo traerlas a tus programas con
import. - A leer la documentación oficial (Javadoc) de Java 25 como un profesional: buscar clases, interpretar firmas, parámetros, valores de retorno y anotaciones como
SinceoDeprecated. - La diferencia completa y definitiva entre miembros de instancia y estáticos: la promesa que la sección 1 dejó citada para hoy.
- Qué es un constructor, cómo leerlos en la documentación y qué es la sobrecarga (que llevas usando desde la UD1 sin saberlo).
- A explorar el API desde IntelliJ con el autocompletado y su documentación integrada, programando «con el manual abierto».
Necesitas tener fresco (de unidades y secciones anteriores):
- De la sección 1 de esta unidad: clase frente a objeto, los tres pasos de
new, referencias ynull, el operador punto, y la presentación informal de los miembros de instancia y estáticos. - De la UD1:
Integer.parseInt()yMath.sqrt()como primeras llamadas estáticas; la claseIO;formatted(); los comentarios Javadoc/** */. - De la UD2: los arrays (
new int[5],.length, recorrido con bucles y operaciones manuales) y los atajos básicos de IntelliJ (Shift+F10,Alt+Enter, el depurador).
2.1 El API de Java: la caja de herramientas ya abierta
En la sección 1 te pedí que hicieras Ctrl+clic sobre la palabra String y pasearas por su código fuente. Si lo hiciste, descubriste algo que conviene convertir en convicción: String no es magia del lenguaje, sino una clase escrita por personas —con sus campos y sus métodos— que vive en un fichero dentro del JDK. Hoy generalizamos esa idea hasta su verdadera escala: el JDK que tienes instalado no es solo el compilador y la máquina virtual que conociste en la UD1; es también una biblioteca gigante de clases listas para usar, escrita, probada y documentada por los ingenieros de Java a lo largo de casi tres décadas. A esa biblioteca se la llama el API de Java (Application Programming Interface: la interfaz que la plataforma ofrece al programador para construir sobre ella).
El tamaño es difícil de exagerar. Hablamos de miles de clases: clases para texto, para matemáticas, para fechas, para colecciones de datos, para leer ficheros, para hablar por red. Ninguna persona del planeta se la sabe entera, y ninguna necesita sabérsela: los profesionales de Java trabajan a diario con una fracción mínima del API y consultan la documentación para todo lo demás. Por eso esta sección no intenta enseñarte clases: intenta enseñarte a orientarte en el almacén.
Imagínate que te mudas a un piso nuevo y el anterior inquilino —un carpintero jubilado— te deja el trastero lleno de herramientas: miles, ordenadas por estanterías, y cada una con su ficha de instrucciones pegada al mango. Fabricar tú un destornillador sería una tontería; lo razonable es aprender qué estanterías hay y cómo leer las fichas. En esta metáfora, las estanterías son los paquetes del API y las fichas son el Javadoc que leeremos en la sección 2.2. Vamos con las estanterías.
Paquetes: el apellido de cada clase
Un paquete (package) es una agrupación con nombre de clases relacionadas: funciona como el apellido de una clase. La clase Random no se llama solo Random a efectos del compilador: se llama java.util.Random, donde java.util es su paquete. Ese apellido evita colisiones en un mundo donde miles de programadores escriben clases: el JDK, por ejemplo, tiene dos clases llamadas Date —java.util.Date y java.sql.Date— que coexisten sin pelearse precisamente porque viven en paquetes distintos. El nombre completo con paquete se llama nombre cualificado (fully qualified name).
Para esta unidad te interesan cuatro estanterías, todas con clases que usarás en las próximas semanas:
| Paquete | Qué guarda | Clases que ya conoces (o conocerás) | Cuándo en el curso |
|---|---|---|---|
java.lang |
El equipamiento básico del lenguaje | String, Math, Integer, IO, todas las excepciones |
Lo usas desde la UD1; toda la unidad |
java.util |
Utilidades generales | Arrays (UD2), Scanner (UD1), Random (sección 5) |
Toda la unidad; colecciones en UD5 |
java.math |
Aritmética de precisión arbitraria | BigInteger, BigDecimal |
Pinceladas puntuales cuando la precisión importe |
java.time |
Fechas, horas y duraciones | LocalDate, LocalTime, Duration |
Sección 6 de esta unidad |
La trampa más clásica del tema
Math no vive en java.math. La clase Math está en java.lang, junto a String e Integer, y por eso nunca has necesitado importarla. El paquete java.math es otro barrio: el de BigInteger y BigDecimal, la aritmética de precisión ilimitada que se usa cuando un long se queda corto o cuando el dinero no admite errores de redondeo. Confundir los dos es el despiste clásico de examen («¿en qué paquete está Math?») y una pregunta habitual en entrevistas juniors.
Por encima de los paquetes hay un nivel más de organización que te va a aparecer escrito en varios sitios, así que mejor presentárselo ya: los módulos. Un módulo es un cajón con nombre que agrupa paquetes, y java.base es el cajón maestro: el núcleo esencial de la plataforma, que contiene los cuatro paquetes de la tabla anterior y muchos más. Del sistema completo de módulos no nos ocuparemos en el ciclo; te basta con reconocer la palabra, porque la verás en la URL de la documentación (sección 2.2) y en algún mensaje del compilador.
flowchart LR
jdk["JDK 25 · el API de Java (miles de clases)"]
base["java.base · el módulo núcleo"]
lang["java.lang\n(el bolsillo: siempre contigo)"]
util["java.util\n(la caja de herramientas general)"]
math["java.math\n(la aritmética de precisión)"]
time["java.time\n(la relojería del API)"]
c1["String · Math · Integer · IO\ny todas las excepciones"]
c2["Arrays · Random · Scanner"]
c3["BigInteger · BigDecimal"]
c4["LocalDate · LocalTime · Duration"]
jdk --> base
base --> lang
base --> util
base --> math
base --> time
lang --> c1
util --> c2
math --> c3
time --> c4
style jdk fill:#2e7d32,color:#ffffff,stroke:#1b5e20
style base fill:#1b5e20,color:#ffffff,stroke:#0d330f
style lang fill:#c8e6c9,color:#000000,stroke:#2e7d32
style util fill:#c8e6c9,color:#000000,stroke:#2e7d32
style math fill:#c8e6c9,color:#000000,stroke:#2e7d32
style time fill:#c8e6c9,color:#000000,stroke:#2e7d32
El import: un apodo para el compilador
¿Y cómo se usa una clase de otro paquete? Tienes dos opciones. La primera es escribir su nombre cualificado completo cada vez: java.util.Random dado = new java.util.Random();. Funciona, pero es insufrible y nadie lo hace. La segunda es declarar al principio del fichero un import:
Con esa línea le dices al compilador: «en lo que queda de fichero, cuando escriba Random, me refiero a java.util.Random». Y aquí conviene desmontar un malentendido frecuente, porque afecta a cómo piensas sobre la memoria: importar no es cargar. El import no copia código a tu programa, no consume memoria y no hace nada en tiempo de ejecución; es puro azúcar para el compilador, un apodo que escribes una vez para no repetir el apellido veinte veces. Tu programa usaría exactamente la misma memoria con import que con nombres cualificados a mano.
Hay una regla que ya conoces de la sección 1 y que ahora queda integrada en el sistema completo: java.lang se importa siempre de forma automática en todo programa Java. Por eso String, Math, Integer y IO nunca han necesitado una línea de import en ningún programa tuyo. Todo lo demás —java.util, java.time, java.math— está a un import de distancia.
Sobre la forma del import, dos matices de estilo. Primero, existe la variante «comodín»: import java.util.*;, que importa bajo demanda todas las clases del paquete. Es legal y la verás en código ajeno, pero en este curso no la usaremos: con el import de una sola clase, cualquiera que lea tu fichero ve de un vistazo qué clases foráneas usa el programa, y se evitan sorpresas cuando dos paquetes exportan clases con el mismo nombre. Segundo, los imports se colocan al principio del fichero, después de la eventual declaración de paquete (en seguida la verás) y antes de cualquier código.
La verdad completa sobre los import (JEP 512)
En la sección 1 te dije que había que «decirle al compilador dónde vive» la clase Random, y por eso escribimos import java.util.Random;. Ha llegado el momento de completar el relato, porque los ficheros compactos que usamos en el curso (los de void main() sin clase visible, JEP 512) reciben un regalo: todo el módulo java.base viene preimportado automáticamente, como si el fichero empezara con una línea invisible import module java.base; (la importación de módulos, JEP 511, es otra novedad de Java 25). En consecuencia, en nuestros programas el import java.util.Random; es en realidad opcional: el compilador encontraría Random igualmente.
¿Y entonces por qué lo seguimos escribiendo? Tres razones. Documenta de un vistazo qué clases foráneas usa el programa (los imports son el «equipaje declarado» del fichero). Evita ambigüedades si algún día dos paquetes traen clases homónimas. Y te acostumbra al Java «de verdad» que escribirás desde la UD4, donde las clases propias viven en paquetes con nombre y el import deja de ser opcional. Un buen hábito a coste cero.
El pariente raro: import static
Existe una variante que verás en código profesional: import static java.lang.Math.PI;, que importa miembros concretos de una clase (ese campo, esos métodos estáticos) para escribirlos sueltos: PI a pelo en vez de Math.PI. Es legal desde hace muchas versiones y puede acortar fórmulas matemáticas densas, pero oculta de dónde viene cada nombre, así que en este curso no la usaremos. Si te la cruzas leyendo código, ya sabes qué significa.
El paquete sin nombre: donde viven (por ahora) tus programas
Una última pieza del puzle: ¿en qué paquete viven nuestros ficheros compactos? En ninguno con nombre: viven en el paquete sin nombre (unnamed package), la zona de tránsito que Java reserva para programas pequeños. Para tus ejercicios de una pantalla es perfecta, pero el código profesional huye de ella: sin paquete no hay apellido, y en un proyecto con cientos de clases los choques de nombres están garantizados. Cuando en la UD4 empieces a escribir clases propias, dejarán de ser ficheros compactos y pasarán a vivir en paquetes con nombre; en este módulo usaremos jams.programacion.ud3 para la unidad actual. Así se verá esa cabecera el día que cruces esa puerta (es un adelanto de cabecera: el cuerpo de la clase llegará con la UD4):
Fíjate en el orden de las dos primeras líneas, porque es invariable en todo Java: primero package (el apellido de TUS clases), luego los import (los apodos de las clases ajenas que vas a usar), y después el código. Ese orden lo has estado viendo invertido en los ficheros compactos —donde no hay package y los import van solos al principio— y así seguirá siendo hasta la UD4.
2.2 Leer la Javadoc: el manual de instrucciones del API
Volvamos a la metáfora del trastero: cada herramienta tiene su ficha de instrucciones pegada al mango. En el API de Java, ese papel se llama Javadoc: la documentación oficial, uniforme y generada automáticamente para todas las clases de la plataforma. Y antes de entrar en cómo se lee, instala la actitud correcta: nadie memoriza el API; nadie necesita hacerlo. El profesional de Java consulta la documentación varias veces al día, sin la menor vergüenza, igual que un cocinero consulta su libro de recetas. La destreza que separa a quien «googlea a ciegas y copia lo primero que encuentra» de quien resuelve el problema de verdad es, precisamente, saber leer esta documentación. Es la herramienta que más vas a usar durante toda la unidad, y hoy la abrimos por primera vez con criterio.
Dónde está y cómo se organiza
La referencia del JDK 25 vive en la web de Oracle:
Guárdala en la barra de marcadores ahora mismo: es la dirección oficial y la versión que corresponde exactamente a tu JDK. Nada de tutoriales de terceros cuando dudes: la fuente de verdad siempre es esta. La página se organiza exactamente igual que el mapa de la sección 2.1: primero módulos, dentro paquetes, dentro clases. De hecho, la propia URL de una clase te lo delata. Si abres la página de String, su dirección es .../docs/api/java.base/java/lang/String.html: módulo java.base, paquete java.lang, clase String. La documentación es el mapa del API escrito en forma de URL.
En la columna de navegación encontrarás enlaces como Index (todas las clases de la A a la Z), Tree (la jerarquía de herencia completa —sí, la misma herencia que conociste en la sección 1—), Deprecated (las piezas marcadas en desuso) y, sobre todo, la caja de búsqueda, que es tu punto de entrada natural: escribe Random, pulsa Enter y aterrizas directamente en su página.
Anatomía de la página de una clase
Todas las páginas de clase del API siguen el mismo esquema, que es además el esquema de cualquier clase Java bien documentada. Aprender a moverte por una es aprender a moverte por todas:
| Zona de la página | Qué encontrarás | Para qué te sirve |
|---|---|---|
| Declaración de la clase | Firma completa: modificadores, clase padre, interfaces que implementa | Saber si es final, de quién desciende, qué contrato firma |
| Descripción | Varios párrafos explicando qué representa la clase y sus reglas de uso | Entender el propósito antes de tocar un solo método |
| Constructor Summary | Los constructores que ofrece, con descripción de una línea | Elegir cómo nace tu objeto (sección 2.4) |
| Method Summary | El repertorio completo de métodos: firma y descripción de una línea | Ojear todo lo que sabe hacer en 30 segundos |
| Method Detail | Cada método a fondo: Parameters, Returns, Throws, Since | La ficha técnica exacta antes de usarlo |
La estrategia de lectura que te recomiendo para una clase nueva es esa, de arriba abajo: descripción (¿qué es esto?), constructor summary (¿cómo se fabrica?), method summary (¿qué sabe hacer?) y, solo para los métodos que vayas a usar, el detail. Leer el detail de los ochenta métodos de String sería una locura; leerlo del único método que necesitas son treinta segundos bien invertidos.
Cómo se lee un método: la ficha de nextInt
Vamos a leer juntos una ficha real, la del método que ya usaste en la sección 1 con el dado. En la página de java.util.Random, bajando al Method Detail de nextInt, encuentras algo así (traducido):
int nextInt(int bound)Parameters:bound— el límite superior (exclusivo). Debe ser positivo. Returns: un valor int seudoaleatorio, uniformemente distribuido, entre 0 (incluido) y el límite indicado (excluido). Throws:IllegalArgumentException— si el límite no es positivo.
Fíjate en la estructura, porque es idéntica en los miles de métodos del API. Parameters describe cada dato que debes entregar y qué significa. Returns describe qué te devolverá la llamada, con las condiciones exactas. Throws avisa de las excepciones que puede lanzar —y que, como aprendiste en la UD2, puedes capturar con try-catch—. Ahora releamos nuestra propia línea de la sección 1 con esta ficha delante:
Con la documentación leída, esa aritmética deja de ser un conjuro. La ficha dice que nextInt(6) devuelve valores entre 0 (incluido) y 6 (excluido), es decir, de 0 a 5. Nosotros queremos un dado de 1 a 6, así que sumamos 1. Fin del misterio: la documentación acaba de explicarte tu propio código, y a partir de aquí ya no necesitarás memorizar rangos ni fórmulas: podrás deducirlos leyendo la ficha. Este mismo mecanismo —leer la ficha, ajustar la llamada— es el que usarás con cada método nuevo de esta unidad.
Dos anotaciones más que viven en las fichas y que te van a acompañar siempre:
Since:es la partida de nacimiento del miembro: la versión de Java en la que se incorporó.String.repeat()luce unSince: 11; nuestra claseIO, unSince: 25: es más joven que casi todo el API —Stringexiste desde la versión 1.0 del lenguaje—, y ahí está el detalle para demostrarlo. Cuando un método te suene a moderno, elSincete lo confirma.Deprecatedes la etiqueta de jubilación: marca piezas que funcionan pero que conviene no usar, normalmente porque existe una alternativa mejor. La descripción del miembro suele decir cuál es el sustituto recomendado, y esa es la parte que importa: lee qué proponen y mígrate. El API envejece con dignidad —no borra casi nada, para no romper los programas antiguos— pero tú no debes heredar sus vicios. La historia de jubilación más famosa del JDK es la de las clases de fecha antiguas, y la sección 6 de esta unidad te la contará.
¿Y las características en «preview»?
En la navegación de la Javadoc verás un enlace Preview: agrupa el API que aún está en fase de vista previa, a medio camino entre experimental y definitivo. En este curso solo usamos características estables, así que no lo necesitas; pero conviene reconocer la palabra, porque delimita qué parte del API puedes usar en un trabajo profesional sin riesgo.
Hay un detalle bonito que ata cabos con la UD1: esta documentación no la escribe un equipo aparte. Se genera automáticamente a partir de los comentarios /** ... */ que los propios ingenieros escriben dentro del código fuente del JDK —los mismos comentarios Javadoc que viste en la UD1 y que tú escribirás en tus clases a partir de la UD4—. Por eso, si haces Ctrl+clic sobre nextInt para saltar al fuente (como hiciste con String en la sección 1), verás literalmente el mismo texto de la ficha, pero tumbado en un comentario sobre el método. La doc no es un adorno pegado al código: es el código documentándose a sí mismo.
La Javadoc dentro de IntelliJ: Ctrl+Q
No hace falta abrir el navegador para consultar una ficha. Coloca el cursor sobre cualquier clase, método o campo de tu programa —por ejemplo, sobre nextInt— y pulsa Ctrl+Q (o View → Quick Documentation): IntelliJ te muestra la Javadoc renderizada, sin salir del editor. Es la misma documentación de la web, a un golpe de teclado. La combinaremos con más atajos en la sección 2.5.
Tu primera consulta oficial, paso a paso
Hazlo ahora, conmigo, una vez; las siguientes te saldrán solas:
- Abre https://docs.oracle.com/en/java/javase/25/docs/api/ y márcala como favorita.
- Escribe
Randomen la caja de búsqueda y pulsa Enter: aterrizarás en la página dejava.util.Random. - Lee las dos primeras frases de su descripción: qué es y para qué sirve.
- Baja al Method Summary y localiza
nextIntentre la lista. - Sigue el enlace de
nextInt(int bound)hasta su Method Detail y relee la ficha que acabamos de comentar: Parameters, Returns, Throws. - Repite el ciclo completo con otra clase que conozcas: busca
String, encuentralength()en el Method Summary y lee su ficha. Nada nuevo bajo el sol —«la longitud de esta cadena»—, pero fíjate en la palabra this rondando la descripción: la doc también habla «en instancia».
Cuando este circuito de seis pasos te resulte natural, habrás adquirido la destreza que esta sección considera más importante: la autonomía para descubrir el API por tu cuenta. El resto de la unidad consistirá, precisamente, en ponerte delante de clases nuevas —Math, Random, java.time, StringBuilder, los wrappers— y dejar que la documentación trabaje para ti.
2.3 Instancia frente a estático: la promesa de la sección 1, cumplida
La sección 1 te presentó las dos formas del operador punto «de pasada» y dejó citado este momento: aquí llega la diferencia exacta. Y aunque el tema parece tener muchas aristas, la clave entera cabe en una pregunta: ¿quién está a la izquierda del punto? Ese algo —la clase o el objeto— se llama el receptor de la llamada, y decidir bien quién es el receptor correcto de cada miembro es, a efectos prácticos, la mitad de todo lo que hay que saber para usar el API con soltura.
Los dos mundos, con precisión
Un método de instancia vive definido en la clase, pero trabaja sobre un objeto concreto: su código usa el estado de ese ejemplar. length() recorre los caracteres de esta cadena; nextInt(6) consulta el estado interno de este generador. Por eso no puedes pedir length() «en general»: la pregunta ni siquiera tiene sentido sin un ejemplar — «¿longitud?... ¿de qué cadena?». Sin objeto que reciba el mensaje, no hay respuesta posible, y si lo intentas directamente sobre la clase, el compilador te lo impedirá (en seguida verás el error exacto).
Un método estático (la palabra clave es static, y ya la irás viendo en firmas y documentación) pertenece a la clase como colectivo: su ejecución no mira el estado de ningún ejemplar, y su resultado depende únicamente de los argumentos que le pases. Integer.parseInt("42") no consulta a ningún «objeto Integer» particular: convierte y listo. Math.max(3, 9) solo mira sus dos argumentos. IO.println(...) solo mira lo que le entregas. Recuerda la analogía de la sección 1: preguntarle a un taxista concreto cuánto costará un trayecto es una consulta de instancia (la respuesta sale de su taxímetro); consultar el listado de tarifas del gremio es una consulta estática (pertenece al colectivo, no a ningún coche, y no requiere que haya un solo taxi en la calle).
De ahí sale la regla mental que te servirá para leer cualquier código ajeno, y que conviene grabar a fuego:
Si la respuesta cambiaría según qué ejemplar concreto responda, el miembro es de instancia. Si cualquier ejemplar daría exactamente la misma respuesta —porque la respuesta solo depende de los argumentos—, el miembro es estático.
Míralo funcionando en un programa que solo usa cosas conocidas:
Tres llamadas, dos mundos. La primera necesita que dado exista: si borras la línea del new, el programa ni compila. Las otras dos funcionarían solas en la primera línea del programa: nadie ha fabricado ningún Math ni ningún Integer.
Clases de utilidad: el mundo de los «todo estático»
Hay clases cuyo repertorio es cien por cien estático: Math, Arrays, IO. Piensa un momento por qué: ¿qué guardarías dentro de «un objeto Math»? No tiene estado, no hay nada que le pertenezca a un ejemplar; sus operaciones son servicios puros del colectivo. A estas se las llama clases de utilidad, y de ellas se deriva una consecuencia práctica: jamás reciben new. Nunca verás new Math(), new Arrays() ni new IO() en código que funcione.
¿Y qué pasa si lo intentas? El propio JDK lo impide por diseño: estas clases esconden su constructor marcándolo como privado, y el compilador te lo hace saber con un mensaje del estilo Math() has private access in java.lang.Math. Ese blindaje es una decisión de encapsulación —de la que ya sabes apreciar la lógica— y en la UD4, sección 6, cuando escribas tus propias clases, lo reproducirás tal cual para tus utilidades. Por ahora, quédate con la regla de lectura: clase de utilidad = clase sin objetos = todo se pide a la clase.
Otras clases, en cambio, viven en el mundo contrario. Random es el ejemplo que ya manejas: casi todo su repertorio es de instancia, porque cada objeto guarda su propia semilla y su propia secuencia. Y las clases más ricas —como verás en seguida con String— mantienen ambos mundos abiertos a la vez.
| Miembro de instancia | Miembro estático | |
|---|---|---|
| Se pide a... | un objeto concreto: referencia.metodo() |
la clase: Clase.metodo() |
| Su código puede usar... | el estado de ese objeto | solo sus argumentos (y otros miembros estáticos) |
Necesita new antes de la llamada |
sí | no |
| Ejemplos que ya conoces | length(), nextInt(6), toUpperCase() |
parseInt("42"), sqrt(2), IO.println(...) |
| Si lo pides al receptor equivocado... | Clase.metodo() → no compila |
vía referencia: compila, pero es mala praxis |
La última fila merece su propio desarrollo, porque los errores de esta frontera son los más frecuentes del primer trimestre. Vamos a verlos uno a uno.
Los tres errores de la frontera
Error 1: pedirle a la clase lo que solo un objeto sabe. Escribe String.length() y el compilador responde con el clásico de los clásicos:
Léelo despacio, porque es un mensaje que verás cientos de veces en tu vida: «el método no estático length() no puede ser referenciado desde un contexto estático». Traducción a tu modelo mental: le pediste la longitud a la plantilla, y la plantilla no tiene caracteres; solo las instancias los tienen. La plantilla ni siquiera sabría por dónde empezar a contestar. Solución: fabrica (o localiza) una cadena concreta y pídeselo a ella: IO.println("hola".length());.
Error 2: fabricar lo infabricable. Escribe new Math() y el compilador te recuerda que el constructor de Math es privado (has private access). Ya sabes la lectura: clase de utilidad, sin objetos por diseño. No hay aquí truco que valer: si un miembro es estático, se pide a la clase.
Error 3 (el cobarde): llamar a un estático a través de un objeto. Java, por razones históricas, permite invocar un método estático usando una referencia como receptor:
Eso compila y funciona —devuelve "42 puntos"—, pero fíjate en la aberración: el resultado ignora por completo a frase; la llamada se ejecuta como si hubieras escrito String.format(...). Es una puerta que Java dejó abierta y que solo siembra confusión: quien lee frase.format(...) entiende que la respuesta depende de frase, y es mentira. IntelliJ lo subraya en cuanto lo escribes, avisando que estás accediendo a un método estático a través de una instancia. La regla de estilo es absoluta: el estático se pide siempre a la clase, con su nombre: String.format(...). (El método format llega a fondo en la sección 3; hoy quédate únicamente con la regla.)
Campos estáticos: los datos del colectivo
La distinción instancia/estático no es exclusiva de los métodos: los campos también se reparten en los dos mundos. Un campo estático es un dato que pertenece a la clase como colectivo y del que existe una sola copia compartida, en lugar de una copia por objeto. El caso de uso rey en el API son las constantes de clase: valores fijos, con nombre, que la clase publica para que los uses sin reescribirlos jamás.
Ya conoces dos, y van a acompañarte toda la unidad: Math.PI (3.141592653589793, la constante con más siglos de servicio del cálculo) e Integer.MAX_VALUE (2147483647, el mayor int representable —un adelanto de la sección 8, donde estudiaremos los wrappers—). Junto a ellas, Integer.MIN_VALUE, Math.E y muchas otras siguen el mismo patrón: se leen con la clase como receptor, sin new alguno, y sus nombres van en MAYUSCULAS_CON_BARRAS_BAJAS —la convención de constantes que conociste en la UD1—.
Contrasta las dos columnas de ese programa: Math.PI es del colectivo (una copia, compartida, se lee en la clase); la longitud de saludo es de ese objeto concreto (cada String tiene la suya). Campos de clase frente a campos de objeto: el mismo reparto que ya hicimos con los métodos.
La joya de la corona: diseccionar System.out.println
Llega el momento de desmontar la llamada más famosa de Java, esa que escribiste mil veces en la UD1 antes de conocer a IO. Seguro que la recuerdas:
Hoy puedes leerla completa, eslabón a eslabón, porque ya dominas todos los conceptos que intervienen:
Es una cadena de puntos de dos eslabones que atraviesa los dos mundos: el primero (System.out) baja de la clase a un campo estático, que resulta guardar un objeto; el segundo (.println(...)) llama a un método de instancia de ese objeto. Un campo estático puede guardar una referencia —recuerda la sección 1: una flecha hacia el montón—, y sobre esa flecha se puede seguir encadenando. La mecánica es idéntica a la del encadenado frase.strip().toUpperCase() que ya analizaste; solo que aquí el primer eslabón es un campo de clase.
flowchart LR
sys["System\n(la clase · java.lang)"]
out["out\n(campo ESTÁTICO: guarda un objeto\nPrintStream ya creado)"]
p["println(...)\n(método de INSTANCIA\nde ese PrintStream concreto)"]
sys -- "primer punto" --> out
out -- "segundo punto" --> p
style sys fill:#2e7d32,color:#ffffff,stroke:#1b5e20
style out fill:#c8e6c9,color:#000000,stroke:#2e7d32
style p fill:#fff3e0,color:#000000,stroke:#e65100
¿Y por qué el curso usa IO.println(...) en su lugar? Precisamente para quitarte esa ceremonia los primeros meses: la clase IO de Java 25 (JEP 512) ofrece println como método estático directo —Clase.metodo() en un solo eslabón— y por dentro delega en ese mismo System.out. Ambas pintan en la misma consola; la tuya es simplemente el ascensor exprés. Pero System.out.println sigue estando en cada programa Java del planeta, así que de ahora en adelante dejará de ser un conjuro y será una frase con gramática completa.
Un detalle fino: ¿por qué println acepta lo que le eches?
Si haces Ctrl+Q sobre println, verás que su parámetro es de tipo Object: «cualquier objeto». Entonces, ¿por qué compila IO.println(42) si 42 es un int, un primitivo y no un objeto? La respuesta se llama autoboxing: Java convierte automáticamente el primitivo en su versión orientada a objetos (un objeto Integer) para que quepa en el parámetro. La sección 8 de esta unidad le dedica un análisis completo, porque ese truco tiene afectación en memoria y rendimiento. Hoy basta con que sepas que el embrague existe.
Las fábricas estáticas: el puente entre los dos mundos
Queda una última pieza del reparto, y es la más elegante. Algunas clases ofrecen métodos estáticos cuyo trabajo es fabricar objetos y devolverlos ya listos. Se llaman fábricas estáticas, y el ejemplo que te espera en la sección 6 es LocalDate.now(): una llamada al colectivo (LocalDate, la clase) que te devuelve un objeto —la fecha de hoy— sobre el que seguirás trabajando con métodos de instancia. El puente entre ambos mundos en una sola expresión: LocalDate.now().getYear() es «fábrica estática que crea el objeto; método de instancia que pregunta a ese objeto».
¿Por qué existen, si ya está new? Dos motivos que podrás apreciar de primera mano cuando lleguen. Primero, el nombre: LocalDate.now() o LocalDate.of(2026, 10, 30) dicen lo que hacen, mientras que new LocalDate(...) no dice nada. Segundo, el control: algunas clases —LocalDate entre ellas— esconden sus constructores y solo permiten nacer por fábrica, para garantizar que todos sus objetos salgan validados. En la sección 5 verás que Random nace por constructor, en la 6 que LocalDate nace por fábrica, y en la UD4 —sección 3— escribirás tus propios constructores y entenderás la elección desde el otro lado del mostrador.
¿Cómo saber, ante un miembro nuevo, cuál es cuál?
Tres vías, en orden de rapidez, y las tres a tu alcance desde hoy:
- La regla mental: ¿la respuesta dependería de un ejemplar concreto? Regla de bolsillo, funciona incluso leyendo código en papel.
- El autocompletado por receptor: en IntelliJ, lo que aparece tras escribir el punto depende de quién sea el receptor — una referencia lista los miembros de instancia; un nombre de clase lista los estáticos. Es la vía rápida mientras programas, y la protagonista de la sección 2.5.
- La firma en la documentación: tanto en la Javadoc web como en
Ctrl+Q, la firma completa del miembro incluye, cuando procede, el modificadorstatic. La fuente de verdad, para casos de duda.
2.4 Constructores: el menú de nacimiento de cada clase
Repasemos los tres pasos de new que establecimos en la sección 1: reserva memoria en el montón, inicializa el objeto y devuelve la referencia. El paso central —la inicialización— no es magia: lo dirige el constructor, el código de la clase que deja el objeto listo para trabajar (el que arranca la semilla interna de un Random, por ejemplo). Y aquí viene el matiz que hoy añade nada menos que vocabulario nuevo: los paréntesis que escribes junto a new no son decoración. Son la puerta de entrada del constructor: ahí decides cuál de los constructores de la clase se ejecuta y qué datos le entregas de partida.
La buena noticia es que ya sabes leerlos, porque viven exactamente donde acabas de aprender a mirar: en la Javadoc, bajo el Constructor Summary. Abre la página de java.util.Random y compruébalo: ofrece dos constructores, y la descripción de cada uno cuenta una historia distinta:
| Constructor | Qué hace (según su ficha) | Cuándo lo quieres |
|---|---|---|
Random() |
Crea un generador con una semilla «impredecible», distinta en cada ejecución | Juegos, sorteos, simulaciones: cada ejecución, distinta |
Random(long seed) |
Crea un generador con la semilla que TÚ le das | Experimentos y pruebas: cada ejecución, idéntica (sección 5) |
Mira lo que acaba de pasar: elegir constructor es elegir el nacimiento del objeto. Con new Random() compras sorpresa; con new Random(42) compras repetición. El objeto que nace de cada uno se comporta de forma radicalmente distinta a lo largo de toda su vida, y la diferencia se decidió en una sola línea, con un par de paréntesis. Compruébalo en carne propia:
Ejecuta ese programa tres veces y anota los números: son siempre los mismos tres valores. Cambia la semilla a 7 y obtendrás otra secuencia distinta... pero también constante entre ejecuciones. Vuelve a new Random() (sin argumentos) y cada ejecución dará valores nuevos. Acabas de presenciar, sin necesidad de teoría adicional, para qué sirve un constructor con parámetros: fijar el estado inicial que condicionará todo el resto de la vida del objeto. La sección 5 convertirá esta curiosidad en una herramienta profesional de depuración (la reproducibilidad); hoy quédate con la mecánica.
La sobrecarga: mismo nombre, distinta lista de parámetros
Que una clase ofrezca varios constructores con el mismo nombre (el de la clase) y distinta lista de parámetros tiene nombre propio: sobrecarga (overloading). La regla es simple y el compilador la aplica con rigor: ante varias versiones del mismo nombre, elige la que encaja con los argumentos que tú has escrito. Escribe new Random() y activa el constructor sin parámetros; escribe new Random(42) y activa el que recibe un long. Misma palabra, dos vidas distintas, seleccionadas por los argumentos.
Y aquí viene la revelación bonita de la sección: llevas usando sobrecarga desde el primer mes de curso, sin que nadie te lo dijera. La clase IO —esa que creías conocer de memoria— mantiene una familia de métodos sobrecargados. Mira su repertorio completo, sacado directamente de su Javadoc:
| Llamada | Versión que se ejecuta | Para qué |
|---|---|---|
IO.println() |
println() — sin argumentos |
Imprimir una línea en blanco |
IO.println("hola") |
println(Object obj) — un argumento |
Imprimir lo que le eches y saltar de línea |
IO.readln() |
readln() — sin argumentos |
Leer una línea tecleada por el usuario |
IO.readln("Nombre: ") |
readln(String prompt) — un argumento |
Leer una línea mostrando antes un mensaje guía |
Cuando en la UD1 escribías IO.println("hola") y en otro programa IO.println(42), estabas invocando siempre la misma versión (la de Object, con el primitivo autoboxeado gracias al embrague que mencionamos antes), y cuando alternabas IO.readln() con IO.readln("Dime tu edad: "), cambiabas de versión sin saberlo. Nadie te lo explicó porque no hacía falta; pero a partir de hoy, cuando veas una lista de métodos con el mismo nombre en el autocompletado o en la Javadoc, ya no te parecerá un despiste de los diseñadores: es una familia sobrecargada, y tú eliges el miembro con los argumentos.
La sobrecarga se aplicará igual a los métodos y a los constructores que escribirás en la UD4 (secciones 3 y 5, donde además aprenderás a encadenar constructores con this(...)). Por hoy, la destreza que se te exige es de lectura: ante varios constructores en la Javadoc, leer cada descripción y elegir conscientemente el nacimiento que conviene a tu programa.
El caso de las clases que esconden sus constructores
Si abres ahora la Javadoc de LocalDate y buscas su Constructor Summary, la encontrarás vacía o casi: sus constructores son privados y la clase solo permite nacer por fábricas estáticas — LocalDate.now(), LocalDate.of(2026, 10, 30) —, tal y como adelantamos en la sección 2.3. Es el patrón contrario a Random, y coexisten en el API por motivos de diseño que sabrás apreciar con la UD4 a cuestas. No te extrañe, pues, que algunas clases «no se dejen» instanciar con new: te están indicando por dónde quieren que entres.
2.5 IntelliJ: la API en la punta de los dedos
Toca la última herramienta de la sección, y no es la menor: el entorno donde todo lo anterior se vuelve fluido. IntelliJ conoce el API completo —indexó el JDK la primera vez que abriste el proyecto, en la UD1— y está diseñado para que nunca programes de memoria, sino dialogando con el editor. La destreza que define a un programador productivo con Java no es recitar métodos: es un circuito de descubrimiento que ejecuta en segundos, tantísimas veces al día que se vuelve reflejo. Vamos a montarlo por piezas.
La técnica del receptor: Ctrl+Space
Escribe generador seguido de un punto y detente un instante: IntelliJ despliega la lista de miembros de instancia del objeto — todo lo que un Random concreto sabe hacer (nextInt, nextBoolean, nextDouble...). Ahora borra y escribe Random (mayúscula, la clase) seguido de punto: la lista cambia — muestra los miembros estáticos que la clase ofrece al colectivo. Y remata el experimento con Math + punto: solo estáticos, a saco (abs, max, sqrt, PI...).
Ese es el truco del receptor, y es exactamente la vía rápida número dos de la sección 2.3: lo que aparece tras el punto lo filtra quién está antes del punto. Sin abrir ninguna documentación, el autocompletado ya te está diciendo qué puedes pedir a cada receptor. Si un día dudas de si un miembro es de instancia o estático, este experimento de quince segundos te lo responde.
El atajo oficial es Ctrl+Space (autocompletado básico), aunque IntelliJ también despliega la lista solo con escribir el punto. Acepta con Enter y observa un detalle delicioso: el IDE escribe la llamada completa —paréntesis incluidos— y coloca el cursor dentro, esperando los argumentos.
Los dos acompañantes: Ctrl+Q y Ctrl+P
El circuito se completa con dos atajos que ya puedes situar:
Ctrl+Q(Quick Documentation): sobre cualquier clase, método o campo, abre su ficha Javadoc renderizada —la misma de la sección 2.2— sin salir del editor. Dudas de qué hacenextInt: cursor encima,Ctrl+Q, y ahí está la ficha con sus Parameters, Returns y Throws. Y si la firma empieza porstatic, ya sabes en qué mundo vive.Ctrl+P(Parameter Info): colócate dentro de los paréntesis de una llamada —entre los argumentos o justo tras abrir el paréntesis— y pulsaCtrl+P: IntelliJ te muestra qué parámetros espera el método, en qué orden y de qué tipos. Es la respuesta instantánea a «¿qué le tengo que pasar a esto?», sin idas y vueltas al navegador.
Añade los dos veteranos que ya conoces y la mesa queda servida: Ctrl+B (o Ctrl+clic) salta al código fuente del JDK, y Alt+Enter propone la solución cuando algo está subrayado — por ejemplo, añadir el import que te falta cuando escribes una clase de java.util sin declararla (pruébalo: borra el import de un programa que use Random y ejecuta el rescate).
| Atajo | Nombre | Qué te da | Cuándo usarlo |
|---|---|---|---|
Ctrl+Space |
Autocompletado básico | Miembros aplicables al receptor | Al escribir cualquier llamada |
Ctrl+Q |
Quick Documentation | Ficha Javadoc en el editor | Antes de usar un miembro nuevo |
Ctrl+P |
Parameter Info | Parámetros, orden y tipos | Dentro de los paréntesis de la llamada |
Ctrl+B |
Go to Declaration | El código fuente del JDK | Cuando quieres ver «cómo está hecho» |
Alt+Enter |
Intención rápida | El arreglo propuesto por el IDE | Cuando algo aparece subrayado |
El circuito de descubrimiento, resumido
Con las cinco piezas montadas, así se ve el flujo completo que usarás el resto de la unidad —y el resto de tu carrera— cada vez que te enfrentes a un miembro del API que no conoces:
flowchart LR
a["Escribe el receptor\n(objeto o clase) + punto"]
b["Ctrl+Space:\nexplora los miembros\nque ofrece ese receptor"]
c["Elige uno\n(por su nombre y su\ndescripcion de una linea)"]
d["Ctrl+P:\nque argumentos espera\ny en que orden"]
e["Ctrl+Q:\nficha completa:\nque devuelve, que lanza"]
a --> b --> c --> d --> e
style a fill:#c8e6c9,color:#000000,stroke:#2e7d32
style b fill:#2e7d32,color:#ffffff,stroke:#1b5e20
style c fill:#c8e6c9,color:#000000,stroke:#2e7d32
style d fill:#2e7d32,color:#ffffff,stroke:#1b5e20
style e fill:#2e7d32,color:#ffffff,stroke:#1b5e20
De tecla a tecla, el circuito entero toma menos tiempo que leer su descripción. Y conviene repetirlo: usar el autocompletado no es vagancia ni trampa — es la forma natural de programar en un lenguaje con un API de miles de clases, exactamente igual que escribir con corrector activado no es trampa al escribir. El diccionario del lenguaje lo aporta el IDE; el criterio de qué pedir y a quién, lo aportas tú. Eso sí: cuando aceptes una sugerencia, acostúmbrate a echarle un ojo a su descripción de una línea (o a un Ctrl+Q veloz si el nombre no lo deja claro). Aceptar a ciegas sí sería trampa, y se paga con bugs.
¿Y si uso macOS?
Los atajos de la tabla son los de Windows/Linux, que son los que usamos en el aula. En macOS, IntelliJ traduce casi todos sustituyendo Ctrl por Cmd — la doc rápida y el autocompletado tienen además sus propias combinaciones locales. Si algún día dudas de cómo se llama un atajo en tu teclado, usa Help → Find Action (doble Shift en versiones recientes) y teclea el nombre de la acción: IntelliJ te muestra su atajo exacto y además la ejecuta si pulsas Enter. Esa paleta de acciones es, por sí sola, el atajo maestro que desbloquea todos los demás.
2.6 Práctica guiada: tu primer descubrimiento por la documentación
Cerremos la sección poniendo a trabajar todo lo aprendido en un programa de verdad. Te propongo construir el generador de apodos de guerrero: un programita que combina al azar un sustantivo y un adjetivo — «Lobo Nocturno», «Halcón Feroz» — y que además servirá de banco de pruebas para tu nuevo circuito de descubrimiento. El código base te lo doy entero; las mejoras las descubrirás tú, con la Javadoc y el autocompletado como única brújula. Esa es la gracia.
Escribe este programa en IntelliJ — en un fichero nuevo, Apodos.java, dentro del proyecto que usas desde la UD1 — y ejecútalo un par de veces:
Antes de las misiones, pausa para leer el programa con las gafas nuevas, porque casi cada línea exhibe algo de hoy: el import de la sección 2.1 (opcional pero declarado, como debe ser); el constructor elegido en el new; el método de instancia nextInt recibiendo un argumento; el + de concatenación de la UD1; la regla de la ficha de nextInt funcionando como índice de array de la UD2; y el IO.println —estático— con su parámetro de tipo Object. Un programa de catorce líneas que resume la sección entera.
Ahora, las misiones. Hazlas en orden y sin saltarte la parte incómoda: intenta encontrar la respuesta antes de abrir la solución plegable.
Misión 1 — Leer la ficha de nextInt dentro del editor. Coloca el cursor sobre nextInt y pulsa Ctrl+Q. Localiza en la ficha la frase que habla del límite superior exclusivo. Con ella delante, responde: ¿por qué es garantizado que sustantivos[generador.nextInt(sustantivos.length)] nunca lanza ArrayIndexOutOfBoundsException?
Solución a la misión 1
La ficha dice que nextInt(n) devuelve valores entre 0 (incluido) y n (excluido). Los índices válidos de un array de longitud n son exactamente 0, 1, ... n-1. El rango de la ficha y el rango de índices coinciden al milímetro: el número devuelto siempre cae dentro de la zona segura del array. Esta combinación —referencia.nextInt(array.length)— es un patrón que usarás constantemente, y ahora sabes demostrar con la documentación por qué es segura, no solo que funciona. Es la misma ficha que explicó el + 1 del dado de la sección 1.
Misión 2 — Descubrir un método nuevo en la Javadoc web. Abre la Javadoc de String (caja de búsqueda, String, Enter) y baja a su Method Summary. Tu objetivo: encontrar un método que repita la cadena varias veces. Cuando lo encuentres, úsalo para rodear el apodo con una línea decorativa de 40 signos de igual.
Solución a la misión 2
En el Method Summary de String busca repeat: su ficha dice que devuelve una cadena cuyo valor es la concatenación de la original repetida el número de veces indicado, y luce un Since: 11. La línea decorativa queda así:
Colócala antes y después de la impresión del apodo y tendrás un cartel digno. Dos observaciones de casa: repeat es un método de instancia (la respuesta depende de ESTA cadena: la que repite es la que recibe el mensaje) — fíjate en que la regla mental de la sección 2.3 lo clasifica sin abrir la ficha; y es un adelanto de la sección 3, que estudiará String a fondo. Hoy lo has encontrado tú solo: ese es el método de trabajo.
Misión 3 — El experimento del receptor. En el programa, escribe generador + punto y observa la lista del autocompletado; ciérrala (Escape) y escribe Random + punto. Compara ambas listas y razona la diferencia. Repite ahora con Math + punto.
Solución a la misión 3
Tras generador. aparece el repertorio de instancia de Random: nextInt, nextBoolean, nextDouble, nextLong... — servicios que trabajan sobre el estado interno de un generador concreto. Tras Random. la lista es ridícula: la clase apenas ofrece miembros estáticos — casi todo lo suyo son métodos de instancia. Y tras Math. ocurre lo contrario: solo estáticos (abs, max, min, sqrt, PI, E...), porque Math es una clase de utilidad sin estado. Tres receptores, tres listas distintas, cero documentación consultada: el autocompletado es el mapa interactivo de los dos mundos.
Misión 4 — Elegir nacimiento: la semilla. Cambia el constructor a new Random(42) y ejecuta el programa dos veces completas. Anota los apodos de cada ejecución. Vuelve luego a new Random().
Solución a la misión 4
Con new Random(42), ambas ejecuciones generan exactamente los mismos apodos, y cambiar la semilla a cualquier otro número produce otra pareja fija. Acabas de verificar en tu propia pantalla lo que la tabla de constructores de la sección 2.4 prometía: el constructor con semilla fija el estado inicial del objeto, y ese estado condiciona toda su secuencia futura. La sección 5 explicará por qué eso es una herramienta profesional (reproducir un fallo en una prueba, repetir un sorteo de demostración) y no un truco de salón.
Misión 5 — Personalizar con la sobrecarga de readln. Haz que el programa pregunte el nombre del usuario antes de generar el apodo, usando la versión de readln que muestra un mensaje guía, y saluda con formato «nombre, tu apodo de guerrero es...».
Solución a la misión 5
La clave de la misión es que elijas la versión sobrecargada correcta sin mirar — y si has dudado, Ctrl+P dentro de los paréntesis te la recuerda al instante. El programa completo, con la personalización integrada, queda así:
IO.readln(String prompt) es la sobrecarga con mensaje guía que la tabla de la sección 2.4 documentaba. Fíjate en la elegancia del asunto: el nombre del método no cambia, la llamada no se complica, y el compilador selecciona la versión correcta solo por el hecho de que tú escribiste un argumento entre los paréntesis.
Si has completado las cinco misiones, para y valora lo que acaba de ocurrir: has aprendido dos cosas que no estaban escritas en esta sección — el comportamiento exacto de repeat y el patrón semilla-reproducibilidad — sin que nadie te las explicara. Las sacaste de la documentación oficial y del propio IDE. Esa autonomía es, exactamente, el objetivo de la sección: a partir de la siguiente, cada clase nueva que conozcas —String, Math, Random a fondo, java.time, StringBuilder— podrás anticiparla tú mismo, y las clases del curso serán confirmaciones más que revelaciones.
2.7 Resumen, glosario y checklist
Si tuvieras que quedarte con diez ideas de esta sección, que fueran estas:
- El API de Java son miles de clases listas para usar, organizadas en paquetes (el apellido de cada clase) que cuelgan de módulos;
java.basees el módulo núcleo y contiene los cuatro paquetes estrella de la unidad:java.lang,java.util,java.mathyjava.time. Mathvive enjava.lang, no enjava.math: ese paquete es el deBigIntegeryBigDecimal. Trampa clásica de examen.- El import es un apodo para el compilador, no una carga de código:
import java.util.Random;te deja escribirRandoma secas.java.langviene preimportado en todo programa Java; y en los ficheros compactos de JEP 512, además, todojava.baseviene preimportado de serie. - Nadie memoriza el API: se consulta la Javadoc oficial (https://docs.oracle.com/en/java/javase/25/docs/api/), cuya página de clase se lee de arriba abajo: declaración, descripción, Constructor Summary, Method Summary y el Detail de cada miembro (Parameters, Returns, Throws, Since).
Sincees la versión de Java en la que nació el miembro;Deprecatedavisa de piezas en desuso y suele proponer el sustituto. La doc describe el qué, nunca el cómo: es el contrato de la abstracción.- La pregunta clave ante cualquier llamada: ¿quién es el receptor? Referencia → miembros de instancia; nombre de clase → miembros estáticos.
- Instancia: el método usa el estado de ese objeto concreto (
length(),nextInt()). Estático: pertenece al colectivo y depende solo de sus argumentos (parseInt,sqrt,IO.println). Regla mental: si la respuesta cambiaría según el ejemplar, es de instancia. System.out.printlnes una cadena de dos puntos: clase → campo estático (out, que guarda unPrintStream) → método de instancia (println). Los campos estáticos también existen:Math.PI,Integer.MAX_VALUE, una única copia compartida.- Los paréntesis de
neweligen constructor; varias versiones con el mismo nombre y distintos parámetros es sobrecarga (Random()/Random(42),IO.println× 2,IO.readln× 2). Elegir constructor es elegir el nacimiento del objeto. - El circuito de descubrimiento en IntelliJ: receptor + punto →
Ctrl+Space→ elegir →Ctrl+P(argumentos) →Ctrl+Q(ficha). Programar «con el manual abierto» es la norma profesional, no la excepción.
Glosario de la sección
| Término | Definición en una línea |
|---|---|
| API | Biblioteca de clases listas para usar que la plataforma ofrece al programador |
| Paquete | Agrupación con nombre de clases relacionadas: el «apellido» de una clase |
| Módulo | Cajón que agrupa paquetes; java.base es el núcleo esencial de la plataforma |
| Nombre cualificado | Nombre completo de una clase con su paquete: java.util.Random |
import |
Declaración que apoda una clase para poder escribir su nombre simple |
| Paquete sin nombre | La zona sin apellido donde viven los programas pequeños (los nuestros, por ahora) |
| Javadoc | La documentación oficial, uniforme y generada desde los comentarios /** */ del fuente |
Since |
Anotación Javadoc: versión de Java en la que se incorporó el miembro |
Deprecated |
Anotación Javadoc: miembro en desuso, con sustituto recomendado |
| Receptor | Lo que está a la izquierda del punto: el objeto o la clase que recibe la llamada |
| Miembro de instancia | Miembro que se invoca sobre un objeto concreto y usa su estado |
| Miembro estático | Miembro que se invoca sobre la clase, sin objeto: pertenece al colectivo |
| Clase de utilidad | Clase con repertorio cien por cien estático y sin objetos (Math, Arrays, IO) |
| Campo estático | Dato de la clase con una única copia compartida (Math.PI) |
| Constante de clase | Campo estático de valor fijo, escrito en MAYUSCULAS_CON_BARRAS_BAJAS |
| Constructor | Código de inicialización que new ejecuta sobre el objeto recién creado |
| Sobrecarga | Varias versiones de un mismo nombre con distinta lista de parámetros |
| Fábrica estática | Método estático cuyo trabajo es crear y devolver objetos (LocalDate.now()) |
| Autocompletado | Asistente del IDE que lista los miembros aplicables al receptor (Ctrl+Space) |
Checklist: al terminar, debes ser capaz de...
- [ ] Explicar cómo se organiza el API en módulos, paquetes y clases, y poner un ejemplo de cada nivel (CE 2.7).
- [ ] Decir en qué paquete vive
Math— y por qué no esjava.math— sin mirar ningún apunte (CE 2.7). - [ ] Importar una clase de
java.utily explicar qué hace exactamente elimport, y por quéIOnunca lo necesitó (CE 2.7, CE 2.5). - [ ] Localizar un método en la Javadoc web y extraer sus parámetros, su valor de retorno y sus excepciones (CE 2.7, CE 2.9).
- [ ] Aplicar la regla mental para clasificar un miembro del API como de instancia o estático, y justificar la clasificación (CE 2.4, CE 2.5).
- [ ] Predecir qué lista mostrará el autocompletado tras una referencia y tras un nombre de clase, antes de probarlo (CE 2.9).
- [ ] Diseccionar
System.out.printlnnombrando clase, campo estático y método de instancia (CE 2.1, CE 2.4). - [ ] Elegir entre dos constructores de una clase leyendo sus descripciones en la Javadoc (CE 2.8, CE 2.3).
- [ ] Ejecutar el circuito
Ctrl+Space→Ctrl+P→Ctrl+Qsin ayuda y describir qué aporta cada paso (CE 2.9).
2.8 Autoevaluación de la sección
¿Esto no era la sección 11?
Igual que en la sección anterior: el test oficial de repaso de la unidad vive en la sección 11, dividido por secciones para el repaso de conjunto. Este bloque es una autoevaluación rápida para hacer justo después de leer, sin material y sin presión: si fallas algo, vuelve a la subsección correspondiente antes de continuar. El orden de las preguntas sigue el orden de la sección.
Pregunta 4
La Javadoc de nextInt(int bound) dice que devuelve un valor «between 0 (inclusive) and the specified bound (exclusive)». ¿Qué puede devolver entonces nextInt(10)?
Pregunta 9
IO.readln() e IO.readln("Escribe tu nombre: ") comparten nombre pero reciben distinto número de parámetros. ¿Cómo se llama esta característica del lenguaje?
Pregunta 10
Estás escribiendo un programa y no recuerdas qué ofrece la clase Math. ¿Cuál es la vía MÁS rápida para verlo sin salir de IntelliJ?
Cuando las diez preguntas te salgan sin dudar, tienes el equipamiento completo para el resto de la unidad: sabes dónde viven las clases, cómo leer sus fichas y cómo preguntarles a la clase o al objeto según corresponda. Estás listo para la sección 3 — La clase String en profundidad, donde por fin abriremos de par en par la clase que más has usado en todo el curso: su inmutabilidad, el famoso pool de cadenas que asoma desde la UD1, y el repertorio completo de métodos de búsqueda, transformación y comparación.