Lekce 1 - Úvod do modulů v Javě
Vítejte u e-learning kurzu, ve kterém se seznámíme s důležitou funkcionalitou jazyka Java, s moduly. Dnešní tutoriál bude více teoretický, vysvětlíme si důvod jejich vzniku, popíšeme základní strukturu modulů a jejich klíčové vlastnosti.
Slovo úvodem
Java moduly se poprvé objevily ve verzi Java 9. Autoři Javy se rozhodli, že je potřeba udělat pořádek v závislostech jednotlivých balíčků. Na obrázku níže si můžete udělat představu o zmatku, který mezi závislostmi balíčků panoval:

Obrázek pochází z oficiálních stránek OpenJDK.
Jak vidíte, v závislostech mezi balíčky existují tzv. cyklické závislosti, ať už přímé, či nepřímé. V rámci modularizace Javy byly odstraněny deprecated třídy či celé balíčky. Smazáním některých balíčků bylo docíleno menší velikosti výsledné JRE. Některé části byly sice z Javy odstraněny, ale existují dále ve formě knihoven. Krásným příkladem je JavaFX. V Javě 8 byla součástí JRE, ale od verze 9 ji v JRE již nenajdeme. Pokud chceme JavaFX dále používat, musíme si její samostatné knihovny do projektu přidat jako závislosti.
Na obrázku níže můžeme vidět výsledek práce na modularizaci Javy 9.

Obrázek nalezneme v dokumentaci pro Javu 9.
V modulech existuje jasná hierarchie a hlavně v grafu nenajdeme žádné
cykly. Základní modul, na kterém jsou automaticky závislé všechny další
moduly, se nazývá java.base
. Tento modul
obsahuje balíčky, které jsou - dle autorů Javy - nepostradatelnou
součástí každé aplikace. Mezi tyto balíčky můžeme (mimo jiné)
najít:
java.lang
java.io
java.nio
java.net
java.time
java.util
Třídy z těchto balíčků lze použít v jakémkoliv modulu a
není třeba explicitně definovat závislost na
java.base
modulu. Všechny ostatní moduly se musí
explicitně přidat do závislostí (o závislostech si povíme za
moment).
Struktura složek JDK
Než se pustíme do modulů jako takových, je potřeba si říct něco o struktuře složek v JDK, protože od Javy 9 se velmi změnila. V Javě 8 byla struktura následující:

JDK8 představuje kořenovou složku pro celé JDK:
JDK8/bin/
obsahuje veškeré nástroje, kterými JDK disponuje: javac, jar, javadoc a další,JDK8/db/
obsahuje Java databáze,JDK8/include/
obsahuje hlavičkové soubory pro podporu nativních jazyků za pomoci JNA,JDK8/lib/
obsahuje knihovny používané pro vývoj,JDK8/man/
obsahuje dokumentaci JDK nástrojů,JDK8/jre/
obsahuje soubory Java Runtime Environment, tedy to, co si instalují uživatelé, aby mohli spouštět programy v Javě,JDK8/jre/bin/
obsahuje nástroje pouze pro spuštění Java aplikací (.java
) aJDK8/jre/lib/
obsahuje knihovny specifické pouze pro JRE.
Problém v této struktuře představují duplicitní složky bin a lib. Nehledě na to, že každé JDK v sobě obsahuje také celé JRE.
Podívejme se nyní na nové uspořádání složek v Javě 9 a výše:

JDK9 představuje kořenovou složku pro celé JDK:
JDK9/bin/
má stejný význam jako v Javě 8, jsou v ní uloženy nástroje JDK,JDK9/conf/
obsahuje konfigurační soubory,JDK9/lib/
obsahuje privátní knihovny systému, které nejsou určeny k použití mimo systém a neměly by být modifikovány,JDK9/include/
stejně jako v Javě 8 obsahuje soubory pro podporu nativních jazyků,JDK9/legal/
obsahuje licence jednotlivých modulů aJDK9/jmods/
- obsahuje všechny používané moduly tohoto JDK.
Jak už bylo řečeno, JDK již neobsahuje JRE podsložku. Nástroje z JRE byly přesunuty do JDK. To by mohlo vnucovat myšlenku, že stačí instalovat JDK a JRE vlastně již není potřeba. Není tomu tak. Koncoví uživatelé rozhodně nepotřebují instalovat celé JDK. Zabíralo by zbytečně mnoho místa oproti samotnému JRE.
Dále vidíme, že JDK9 přímo obsahuje samostatnou složku pro moduly -
jmods. V ní najdeme jednotlivé moduly. Každý soubor v této složce
má příponu .jmod
. Ve skutečnosti je to ale obyčejný
zip
archiv. V archivu najdete (mimo jiné) zkompilované
.class
soubory, konfiguraci modulu a použité licence.
Vlastnosti modulů
Když už jsme si řekli důvody, proč se Java modularizovala, pojďme se zaměřit na základní vlastnosti modulů. Jsou celkem tři:
- silná enkapsulace (strong encapsulation),
- definice veřejného rozhraní,
- explicitní definice závislostí.
Silná enkapsulace (strong encapsulation)
Z OOP jistě znáte modifikátory přístupu tříd:
public
, private
, protected
a tzv.
package-private (třída bez modifikátoru přístupu). Moduly
přidávají další úroveň zapouzdření. Tato vlastnost nám říká, že v
základu jsou veškeré třídy, které vytvoříme v rámci modulu,
neveřejné. To znamená, že nebudou dostupné ostatním
modulům.
Definice veřejného rozhraní
Aby bylo možné používat třídy z jiných modulů, je třeba v modulech specifikovat, které balíčky budou veřejně dostupné. Otevření tříd ve vnořených balíčcích se neděje automaticky a je třeba jej specifikovat manuálně.
Explicitní definice závislostí
Když už máme definováno, které balíčky budou veřejně dostupné, musíme také definovat, které balíčky budeme vyžadovat pro běh naší aplikace. Zde je důležité, abychom si pojem definice závislostí nepletli s použitím závislostí pomocí Mavenu či Gradlu. Maven/Gradle nám (mimo jiné) zpřístupní knihovnu požadované verze. Ovšem i knihovna může obsahovat více modulů. A moduly, jak už víme, musí definovat veřejné rozhraní.
Classpath a Modulepath
Classpath bychom již měli znát z předchozích
tutoriálů. Jen pro připomenutí - jedná se o seznam cest, na kterých může
kompilátor Javy a JVM samotná hledat jednotlivé třídy (.class
soubory):
java --classpath cesta/k/vasi/knihovne.jar
Modulepath je novinka zavedená právě kvůli modulům.
Podobně jako classpath obsahuje cesty ke složkám, kde se
moduly nachází. Každá cesta je oddělena ;
:
java --module-path cesta/k/modulum;dalsi/cesta/k/modulum
Dnes jsme si vysvětlili, proč Java zavedla moduly a jaké výhody nám to přináší. Čeká nás ještě trocha teorie, poté si vše postupně ukážeme na konkrétních příkladech. Těším se na vás u dalších lekcí.
V další lekci, Classloader a první modul v Javě, si představíme classloader a jednotlivé druhy modulů a ukážeme si, jak takový modul definujeme.