Obsah
Dokumentace javových programů, dokumentace API
Typy komentářů - dokumentační komentáře
Generování dokumentace
Značky javadoc
Distribuční archívy .jar
Vytvoření archívu, metainformace
Spustitelné archívy
Základním a standardním prostředkem je tzv. dokumentace API
Dokumentace je naprosto nezbytnou součástí javových programů.
Rozlišujeme dokumentaci např. instalační, systémovou, uživatelskou, programátorskou...
Zde se budeme věnovat především dokumentaci programátorské, určené těm, kdo budou náš kód využívat ve svých programech, rozšiřovat jej, udržovat jej. Programátorské dokumentaci se říká dokumentace API (apidoc, apidocs).
Při jejím psaní dodržujeme tato pravidla:
Dokumentujeme především veřejné (public) a chráněné (protected) prvky (metody, proměnné). Ostatní dle potřeby.
Dokumentaci píšeme přímo do zdrojového kódu programu ve speciálních dokumentačních komentářích vpisovaných před příslušné prvky (metody, proměnné).
Dovnitř metod píšeme jen pomocné komentáře pro programátory (nebo pro nás samotné).
od značky // do konce řádku, nepromítnou se do dokumentace API
začínají /* pak je text komentáře, končí */ na libovolném počtu řádků
od značky /** po značku */ může být opět na libovolném počtu řádků
Každý další řádek může začínat mezerami či *, hvězdička se v komentáři neprojeví.
Dokumentace má standardně podobu HTML stránek (s rámy i bez)
Dokumentace je generována nástrojem javadoc z
Lze tedy (základním způsobem) dokumentovat i program bez vložených komentářů!
volbami (options) při spuštění,
použitím jiného tzv. docletu, což je třída implementující potřebné metody pro generování komentářů.
Princip generování ze zdrojových textů pomocí speciálních docletů se dnes používá i po jiné než dokumentační účely - např. pro generátory zdrojových kódu aplikací EJB apod.
javadoc můžeme podrobněji instruovat pomocí značek vkládaných do dokumentačních komentářů, např.:
specifikuje autora API/programu
označuje verzi API, např. "1.0"
informuje, že prvek je zavrhovaný
popisuje informace o výjimce, kterou metoda propouští ("vyhazuje")
popisuje jeden parametr metody
uvedeme, od kdy (od které verze pg.) je věc podporována/přítomna
uvedeme odkaz, kam je také doporučeno nahlédnout (související věci)
/**
* Klasse, die ein Fenster auf dem Bildschirm repräsentiert
* Konstruktor zum Beispiel:
* <pre>
* Window win = new Window(parent);
* win.show();
* </pre>
*
* @see awt.BaseWindow
* @see awt.Button
* @version 1.2 31 Jan 1995
* @author Bozo the Clown
**/
class Window extends BaseWindow {
...
}
Příklad dokumentačního komentáře k proměnné:
/**
* enthält die aktuelle Anzahl der Elemente.
* muss positiv und kleiner oder gleich der Kapazität sein
**/
protected int count;
Tyto a další příklady a odkazy lze vidět v původním materiálu JavaStyleGuide des IGE, odkud byly ukázky převzaty.
javadoc [options] [packagenames] [sourcefiles] [classnames] [@files]
možné volby:
-help, -verbose
-public, -protected, -package, -private - specifikuje, které prvky mají být v dokumentaci zahrnuty (implicitně: -protected)
-d destinationdirectory - kam se má dok. uložit
-doctitle title - titul celé dokumentace
Distribucí nemyslíme použití nástroje typu "InstallShield"..., ale spíše něčeho podobného tar/ZIPu
Java na sbalení množiny souborů zdrojových i přeložených (.class) nabízí nástroj jar.
Sbalením vznikne soubor (archív) .jar formátově podobný ZIPu (obvykle je to ZIP formát), ale nemusí být komprimován.
Kromě souborů obsahuje i metainformace (tzv. MANIFEST)
Součástí archívu nejsou jen .class soubory, ale i další zdroje, např. obrázky, soubory s národními variantami řetězců, zdrojové texty programu, dokumentace...
jar {ctxu} [vfm0M] [jar-file] [manifest-file] [-C dir] files
c - vytvoří archív
t - vypíše obsah archívu
x - extrahuje archív
u - aktualizuje obsah archívu
volby:
v - verbose
0 - soubory nekomprimuje
f - pracuje se se souborem, ne se "stdio"
m - přibalí metainformace z manifest-file
parametr files uvádí, které soubory se sbalí - i nejavové (např. typicky dokumentace API - HTML, datové soubory)
Vezměme následující zdrojový text třídy JarDemo v balíku tomp.ucebnice.jar, tj. v adresáři c:\tomp\pb162\java\tomp\ucebnice\jar:
Vytvoříme archív se všemi soubory z podadresáře tomp/ucebnice/jar (s volbou c - create, v - verbose, f - do souboru):
Vzniklý .jar soubor lze prohlédnout/rozbalit také běžným nástrojem typu unzip, gunzip, WinZip, PowerArchiver nebo souborovým managerem typu Servant Salamander...
Tento archív rozbalíme v adresáři /temp následujícím způsobem:
Vytvoříme jar s manifestem obsahujícím tento řádek:
Main-Class: NázevSpouštěnéTřídy
java
-jarNázevBalíku
.jar
Koncepce I/O proudů v Javě, skládání (obalování vlastnostmi)
Práce se soubory a adresáři, třída File
Binární proudy, třídy InputStream, OutputStream
Znakové proudy, třídy Reader, Writer
Serializace objektů
koncipovány jako "stavebnice" - lze vkládat do sebe a tím přidávat vlastnosti, např.
is = new InputStream(...);
bis = new BufferedInputStream(is);
Téměř vše ze vstupních/výstupních tříd a rozhraní je v balíku java.io.
počínaje J2SDK1.4 se rozvíjí alternativní balík - java.nio (New I/O)
základem je třída java.io.File - nositel jména souboru, jakási "brána" k fyzickým souborům na disku.
používá se jak pro soubory, tak adresáře, linky i soubory identifikované UNC jmény (\\počítač\adresář...)
opět plně platformově nezávislé
na odstínění odlišností jednotlivých systémů souborů lze použít vlastností (uvádíme jejich hodnoty pro JVM pod systémem MS Windows):
Vytvoření konstruktorem - máme několik možností:
vytvoří v aktuálním adresáři soubor s názvem filename
vytvoří v adresáři baseDir soubor s názvem filename
vytvoří v adresáři se jménem baseDirName soubor s názvem filename
vytvoří soubor se (souborovým - file:) URL url
Vytvoření souboru nebo adresáře:
(pro soubor) vrací true, když se podaří soubor vytvořit
(pro adresář) vrací true, když se podaří adresář vytvořit
navíc si dotvoří i příp. neexistující adresáře na cestě
délka (velikost) souboru v bajtech
čas poslední modifikace v ms od začátku éry - podobně jako systémový čas vracený System.currentTimeMillis().
jen jméno souboru (tj. poslední část cesty)
celá cesta k souboru i se jménem
absolutní cesta k souboru i se jménem
adresář, v němž je soubor nebo adresář obsažen
Blíže viz dokumentace API třídy File.
Klíčem je opět třída File - použitelná i pro adresáře
Jak např. získat (filtrovaný) seznam souborů v adresáři?
pomocí metody File[] listFiles(FileFilter ff) nebo podobné
File[] listFiles(FilenameFilter fnf):
FileFilter je rozhraní s jedinou metodou boolean accept(File pathname), obdobně FilenameFilter, viz Popis API java.io.FilenameFilter
Uvedené metody, kromě abstract byte read(), nemusejí být nutně v neabstraktní podtřídě překryty.
uzavře proud a uvolní příslušné zdroje (systémové "file handles" apod.)
poznačí si aktuální pozici (později se lze vrátit zpět pomocí reset())...
...ale jen když platí tohle
přečte bajt (0-255 pokud OK; jinak -1, když už není možné přečíst)
přečte pole bajtů
přečte pole bajtů se specifikací délky a pozice plnění pole b
vrátí se ke značce nastavené metodou mark(int)
přeskočí zadaný počte bajtů
java.io.FilterInputStream - je bázová třída k odvozování všech vstupních proudů přidávajících vlastnost/schopnost filtrovat poskytnutý vstupní proud.
Příklady filtrů (ne všechny jsou v java.io!):
proud s vyrovnávací pamětí (je možno specifikovat její optimální velikost)
proud s kontrolním součtem (např. CRC32)
proud dešifrující data ze vstupu
má metody pro čtení hodnot primitivních typů, např. float readFloat()
počítá současně i haš (digest) čtených dat, použitý algoritmus lze nastavit
dekomprimuje (např. GZIPem) zabalený vstupní proud (má ještě specializované podtřídy)
doplňuje informaci o tom, ze kterého řádku vstupu čteme (zavrhovaná - deprecated - třída)
přidává schopnost informovat o průběhu čtení z proudu
do proudu lze data vracet zpět
Příklad rekonstrukce objektů ze souborů
FileInputStream istream = new FileInputStream("t.tmp");
ObjectInputStream p = new ObjectInputStream(istream);
int i = p.readInt();
String today = (String)p.readObject();
Date date = (Date)p.readObject();
istream.close();
vstupní proud zvukových dat
proud dat čtených z pole bajtů
roura napojená na "protilehlý" PipedOutputStream
proud vzniklý spojením více podřízených proudů do jednoho virtuálního
proud na čtení serializovaných objektů
Ze vstupního binárního proudu InputStream (čili každého) je možné vytvořit znakový Reader pomocí
// nejprve binární vstupní proud - toho kódování znaků nezajímá InputStream is = ... // znakový proud isr // použije pro dekódování standardní znakovou sadu Reader isr = new InputStreamReader(is); // sady jsou definovány v balíku
java.nioCharset chrs = java.nio.Charset.forName("ISO-8859-2"); // znakový proud isr2 // použije pro dekódování jinou znakovou sadu Reader isr2 = new InputStreamReader(is, chrs);
Podporované názvy znakových sad naleznete na webu IANA Charsets.
Obdobně pro výstupní proudy - lze vytvořit Writer z OutputStream.
nebudeme podrobně studovat, zatím stačí vědět, že:
serializace objektů je postup, jak z objektu vytvořit sekvenci bajtů persistentně uložitelnou na paměťové médium (disk) a později restaurovatelnou do podoby výchozího javového objektu.
deserializace je právě zpětná rekonstrukce objektu
aby objekt bylo možno serializovat, musí implementovat (prázdné) rozhraní java.io.Serializable
proměnné objektu, které nemají být serializovány, musí být označeny modifikátorem - klíčovým slovem - transient
pokud požaduje "speciální chování" při de/serializaci, musí objekt definovat metody
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException
private void writeObject(java.io.ObjectOutputStream stream) throws IOException
metody:
DataOutputStream.writeObject(Object o)
Tutoriály k Java I/O: kapitola z Sun Java Tutorial
Demo programy na serializaci (z učebnice): Serializace objektů