Java Dokumentations-Kommentare: Javadoc
1. Überblick
Enthaltene Themen:
-
Lesen von Java-API-Dokumentation
-
Schreiben von Javadoc-Kommentaren
-
zusätzliche Formatierungs- und Gestaltungsmöglichkeiten mit HTML, CSS, eigebetteter Vektorgraphik (SVG)
Ein allgemeinerer Terminus ist "API-Doc" (API = Application Programming Interface + Documentation).
Programmieren kann man in mehrere Teil-Kategorien gliedern: Einige davon sind auf jeden Fall:
-
Verstehen einer Situation, in der Software-Unterstützung gewünscht ist
-
Beherrschen von Algorithmen und sonstiger Programm-Strukturen in der geplanten Programmiersprache
-
Kenntnis, welche für die Aufgabenstellung nützlichen Komponenten verfügbar sind
-
Kenntnis, wie diese Komponenten genutzt werden können
Für die beiden letzten Punkte ist die Dokumentation von Software-Komponenten unverzichtbar. Daher wird in Java ein Konzept bereitgestellt, direkt im Source-Code Nutzungs-Dokumentation zu schreiben.
Es gibt dazu ein Werkzeug: javadoc
, das aus bestehendem, syntaktisch korrektem Java-Source-Code eine gut strukturierte, einheitliche technische HTML-Dokumentation erstellt.
In BlueJ kann die Dokumentation direkt im Editor angesehen werden. Voraussetzung ist, dass der Source-Code syntaktisch korrekt ist.
Dann kann man rechts oben im Editor per Auswahl-Box zwischen "Source Code" und "Dokumentation" umschalten.

2. Externe Informationsquellen
siehe Javadoc - Wikipedia – relativ kompakt (englische Version etwas ausführlicher), übersichtliche Auflistung der Javadoc-Tags (beginnend mit @…
oder eingeschlossen in {@ …}
)
3. Finden und Lesen bestehender API-Dokumentation (z.B. JDK)
-
Klasse
Math
finden: Suchmaschine "oracle javadoc 17 Math" → docs.oracle.com › api › java › lang"
siehe Math (Java SE 17 & JDK 17) → Method Summary -
Klasse
String
finden: Suchmaschine "oracle javadoc 17 String" → docs.oracle.com › api › java › lang"
siehe String (Java SE 17 & JDK 17) → Method Summary
In Arbeit …
TODO: Auffinden mit Suchmaschine incl. Version:
"javadoc 17 String → docs.oracle.com › api › java"
TODO: Struktur einer Klassen-Dokumentationsseite (Kopf, Summaries, Details)
TODO: Link auf z.B. Method-Summary setzen mit …#method.summary + Tipps zum Finden der Link-ID
4. Schreiben von Javadoc-Kommentaren
4.1. Einfaches Einstiegs-Beispiel
Source-Code Klasse Kreis (auf-/einklappbar)
/**
* Einfache Kreis-Klasse.
*
* @author Max Renkin <renkin@spengergasse.at>
* @version 2022-11-28
*/
public class Kreis
{
// Javadoc privater Elemente würde normalerweise nicht angezeigt
private double radius = 1.0; // Einheitskreis
/**
* Konstruktor fuer Objekte der Klasse Kreis.
* @param radius siehe {@link #setRadius(double)}
*/
public Kreis(double radius) {
setRadius(radius);
}
/**
* Setter für den Radius.
* @param radius der Radius in cm
*/
public void setRadius(double radius) {
if (radius <= 0) {
System.out.println("Radius muss positiv sein, gegeben war aber: "
+ radius + " -> bleibt auf " + this.radius);
} else {
this.radius = radius;
}
}
// Selbsterklaerend - kein Javadoc-Kommentar nötig
public double getRadius() {
return radius;
}
/**
* Berechnet den Kreisumfang.
* @return den Kreisumfang in cm
*/
public double calcUmfang() {
return 2*radius*Math.PI;
}
/**
* Berechnet die Kreisflaeche.
* @return die Kreisflaeche in cm²
*/
public double calcFlaeche() {
return radius*radius*Math.PI;
}
/**
* Bildschirmausgabe der Eckdaten. <br>
* Beispiel:
* <pre>=== Kreis mit Radius 3.0cm: ===
* Umfang: 18.84955592153876cm
* Flaeche: 28.274333882308138cm²
* </pre>
*/
public void printInfo() {
System.out.println("=== Kreis mit Radius " + this.radius + "cm: ===");
System.out.println(" Umfang: " + calcUmfang() + "cm");
System.out.println(" Flaeche: " + calcFlaeche() + "cm²");
System.out.println(); // Leerzeile
}
}
Nun wird die Auswirkung bzw. das Ergebnis fehlender bzw. vorhandener Javadoc-Kommentare in den generierten API-Dokumentationsseiten gezeigt.
4.2. Automatisch generierte Dokumentation OHNE jeden Javadoc-Kommentar
Im Anschluss ist ein Beispiel zu sehen, das keinerlei Javadoc-Kommentare enthält. Es ist zu sehen, dass auch bei komplettem Fehlen von Javadoc-Kommentaren eine sinnvolle API-Dokumentation erzeugt wird.
4.2.1. Java-Sourcecode der Klasse (ohne Javadoc-Kommentare)
Zuerst der Java-Sourcecode:
Klasse ohne Javadoc-Kommentare (auf-/einklappbar)
public class PersonOhneJavadoc {
private String name = "--- ---";
private int gebJahr = -9999;
private int groesse = -99;
public PersonOhneJavadoc(String name, int gebJahr) {
setName(name); // groesse wird bewusst nicht gesetzt - keine zwingend nötige Information
if (gebJahr < 1900 || gebJahr > 2030) { // direkt im Konstruktor, da 'gebJahr' unveränderbar (immutable)
System.out.println("FEHLER - ungültiges GebJahr (1900 .. 2030): " + gebJahr // hier OHNE 'this'
+ " - auf " + this.gebJahr + " gesetzt"); // hier MIT 'this'!!
} else {
this.gebJahr = gebJahr;
}
}
public void setName(String name) {
String msgHead = "FEHLER - ungültiger Name: "; // Abkürzungen: msg ... 'message', head ... hier 'Anfangs-Teil'
String msgTail = " -> Wert '" + this.name + "' bleibt bestehen."; // tail ... hier 'End-Teil'
if (name == null) {
System.out.println(msgHead + "null" + msgTail);
} else if (!name.contains(" ")) { // kein Leerzeichen
System.out.println(msgHead + "enthält kein Leerzeichen" + msgTail);
} else if (name.indexOf(" ") != name.lastIndexOf(" ")) { // mehr als 1 Leerzeichen
System.out.println(msgHead + "enthält mehr als 1 Leerzeichen" + msgTail);
} else if (name.startsWith(" ") || name.endsWith(" ")) { // Leerzeichen am Anfang oder Ende
System.out.println(msgHead + "beginnt oder endet mit Leerzeichen" + msgTail);
} else {
this.name = name;
}
}
public void setGroesse(int groesse) {
if (groesse < 50 || groesse > 250) {
System.out.println("FEHLER - ungültige Groesse (50 .. 250): " + groesse + "cm - bleibt auf " + this.groesse);
}
this.groesse = groesse;
}
public String getName() {
return this.name;
}
public int getGebJahr() {
return this.gebJahr;
}
public int getGroesse() {
return this.groesse;
}
public String extractVorname() {
int spacePos = name.indexOf(" "); // kein Check auf -1 (nicht gefunden) nötig, da Prfg in Setter
return name.substring(0, spacePos);
}
public String extractNachname() {
int spacePos = name.indexOf(" "); // kein Check auf -1 (nicht gefunden) nötig, da Prfg in Setter
return name.substring(spacePos + 1);
}
public int calcAlter(int diesesJahr) {
return (diesesJahr < 1900 || diesesJahr > 2030 || gebJahr == -9999) ? -99 : diesesJahr - gebJahr;
}
}
4.2.2. Daraus Generierte Dokumentations-Seite (ohne Javadoc-Kommentare)
Nun die generierte API-Dokumentations-Seite:
Screenshot "nackte" Dokumentationsseite (auf-/einklappbar) – Original-Dokumentationsseite: PersonOhneJavadoc.html ^

Man sieht, dass alles an Struktur-Info extrahiert wird, was zur Nutzung der Klasse mit ihren Methoden verfügbar ist. Eine Erklärung der Bedeutung fehlt natürlich — dazu sind die noch nicht erstellten Javadoc-Kommentare nötig.
4.3. Semantisch angereicherte Dokumentation MIT sinnvollen Javadoc-Kommentaren
4.3.1. Java-Sourcecode der Klasse (angereichert mit Javadoc-Kommentaren)
Klasse MIT Javadoc-Kommentaren (auf-/einklappbar)
/**
* Einfache Personen-Klasse für Demonstrationszwecke vorwiegend zu Javadoc-Kommentaren.
* <p>Es sind nur Konstruktor (mit Parameter), Getter (mit Rückgabewert), Setter (mit Parameter)
* und 3 zusätzliche Methoden (eine mit Parameter UND Rückgabewert) vorhanden.</p>
* <p>Sie dient auch als Beispiel INHALTLICH sinnvoller API-Dokumentation
* (API = Application Programming Interface).</p>
* <p>Eine solche API-Dokumentation soll die Nutzung der Klasse durch andere Programmierer
* <i>ohne Studium des Source-Codes</i> ermöglichen. Daher sind im besten Falle
* <i>alle</i> Infos zu:</p>
* <ul>
* <li>genereller Zweck der Klasse oder Methode</li>
* <li>Einheiten</li>
* <li>Gültigkeitsbereiche</li>
* <li>Sonderbedeutungen bestimmter übergebener und/oder zurückgegebener Werte (null, 0, negativ, ...)</li>
* <li>Fehlermöglichkeiten samt Reaktion der Methode(n)</li>
* <li>...</li>
* </ul>
* <p>anzugeben.</p>
* <i><b>Wichtig:</b> (optionale) Zeilenschaltung nach erstem Satz (". <br>"):
* Leerzeichen nach Punkt ZWINGEND, damit Satz-Ende erkannt wird!</i>
*
* @author renkin@spengergasse.at
* @version 2020-12-06.v1
*/
public class PersonMitJavadoc {
private String name = "--- ---";
private int gebJahr = -9999;
private int groesse = -99;
/**
* Konstruktor für Objekte der Klasse 'PersonMitJavadoc'.
* <p>Name ist veränderbar, Geburtsjahr fix, als dritte Eigenschaft existiert die
* (ebenfalls veränderbare) Größe, die zu Beginn auf 'nicht gesetzt' (= -99) steht.
* </p>
*
* @param name Details siehe Setter {@link #setName}
* @param gebJahr das Geburtsjahr als 4-stellige Zahl (z.B. <i>1999</i>) zw. 1900 und 2030
*/
public PersonMitJavadoc(String name, int gebJahr) {
setName(name); // groesse wird bewusst nicht gesetzt - keine zwingend nötige Information
if (gebJahr < 1900 || gebJahr > 2030) { // direkt im Konstruktor, da 'gebJahr' unveränderbar (immutable)
System.out.println("FEHLER - ungültiges GebJahr (1900 .. 2030): " + gebJahr // hier OHNE 'this'
+ " - auf " + this.gebJahr + " gesetzt"); // hier MIT 'this'!!
} else {
this.gebJahr = gebJahr;
}
}
/**
* Setter für (vollen) Namen.
*
* @param name VOLLER Name im Format "Vorname Nachname" (in dieser Reihenfolge, genau <b>ein</b> Leerzeichen). <br>
* Wenn ein Teil unbekannt, auf '---' setzen. <br>
* Muster für gültige Werte: nicht null, genau 1 Leerzeichen, dieses nicht am Anfang oder Ende.
* Wenn übergebener Wert ungültig, <i>bleibt der alte Wert</i>
*/
public void setName(String name) {
String msgHead = "FEHLER - ungültiger Name: "; // Abkürzungen: msg ... 'message', head ... hier 'Anfangs-Teil'
String msgTail = " -> Wert '" + this.name + "' bleibt bestehen."; // tail ... hier 'End-Teil'
if (name == null) {
System.out.println(msgHead + "null" + msgTail);
} else if (!name.contains(" ")) { // kein Leerzeichen
System.out.println(msgHead + "enthält kein Leerzeichen" + msgTail);
} else if (name.indexOf(" ") != name.lastIndexOf(" ")) { // mehr als 1 Leerzeichen
System.out.println(msgHead + "enthält mehr als 1 Leerzeichen" + msgTail);
} else if (name.startsWith(" ") || name.endsWith(" ")) { // Leerzeichen am Anfang oder Ende
System.out.println(msgHead + "beginnt oder endet mit Leerzeichen" + msgTail);
} else {
this.name = name;
}
}
/**
* Setter für Körpergröße.
* @param groesse in <b>cm</b> zwischen 50 und 250. Wenn übergebener Wert ungültig, <i>bleibt der alte Wert</i>
*/
public void setGroesse(int groesse) {
if (groesse < 50 || groesse > 250) {
System.out.println("FEHLER - ungültige Groesse (50 .. 250): " + groesse + "cm - bleibt auf " + this.groesse);
}
this.groesse = groesse;
}
/**
* Getter für Name.
* @return der Name ('--- ---' vor erstem gültigen Setzen)
*/
public String getName() {
return this.name;
}
/**
* Getter für Geburtsjahr.
* @return das Geburtsjahr (-9999 vor erstem gültigen Setzen)
*/
public int getGebJahr() {
return this.gebJahr;
}
/**
* Getter für Körpergröße.
* @return Größe in cm (-99 vor erstem gültigen Setzen)
*/
public int getGroesse() {
return this.groesse;
}
/**
* Extrahiert Namensteil <b>vor</b> dem Leerzeichen (EN: space). <br>
* Keine Prüfung auf Vorhandensein des Leerzeichens nötig, da dies bereits im Setter geschieht.
*
* @return liefert Vorname ("---" vor erstem gültigen Setzen)
*/
public String extractVorname() {
int spacePos = name.indexOf(" "); // kein Check auf -1 (nicht gefunden) nötig, da Prfg in Setter
return name.substring(0, spacePos);
}
/**
* Extrahiert Namensteil <b>nach</b> dem Leerzeichen (EN: space).<br>
* Keine Prüfung auf Vorhandensein des Leerzeichens nötig, da dies bereits im Setter geschieht.
*
* @return liefert Nachname ("---" vor erstem gültigen Setzen)
*/
public String extractNachname() {
int spacePos = name.indexOf(" "); // kein Check auf -1 (nicht gefunden) nötig, da Prfg in Setter
return name.substring(spacePos + 1);
}
/**
* Berechnet ungefähres Alter.
* @param diesesJahr das Jahr, in dem das jeweilige Alter bestimmt werden soll. <br>
* Gültig zw. 1900 und 2030 (wie Gültigkeitsbereich von Geburtsjahr).
* @return das ungefähre Alter in Jahren. Bei nicht gültigem 'diesesJahr' oder Geburtsjahr
* {@link #PersonMitJavadoc}: -99
*/
public int calcAlter(int diesesJahr) {
return (diesesJahr < 1900 || diesesJahr > 2030 || gebJahr == -9999) ? -99 : diesesJahr - gebJahr;
}
}
4.3.2. Mit Javadoc-Kommentaren angereicherte Dokumentations-Seite
Obige Klasse ermöglicht nun das Generieren folgender API-Dokumentation (im Anschluss ein unvollständiger Screenshot, hier die vollständige HTML-Seite zu PersonMitJavadoc.html^):
Screenshot Beginn der "semantisch angereicherten" Dokumentationsseite (auf-/einklappbar)

4.4. HowTo zum Erstellen von Javadoc-Kommentaren
4.4.1. Überblick
-
Javadoc-Kommentare werden (in der Standard-Einstellung) nur direkt VOR 'public'-Elementen ausgewertet – also vor:
-
Klassendeklaration
public class SomeClass { … }
-
public Methoden
public void aMethod() { … }
-
public Konstante (z.B.
Math.PI
):public static final String TEXT_NONSENSE = "Irgendein Nonsense"
-
weitere Elemente, die wir noch nicht besprochen haben
-
-
Der Javadoc-Kommentar ist (Ab Java-Version 9, Mitte 2017) im Wesentlichen leicht ergänztes HTML5.
Details siehe unten ##. -
Der erste Satz (bis zum ersten Punkt gefolgt von Leerzeichen) hat jeweils besondere Bedeutung.
Nur dieser wird im Übersichts-Bereich ("Summary") angezeigt, der gesamte Kommentar ist in den Details (schnell erreichbar über den verlinkten Methodennamen). Falls dahinter eine explizite Zeilenschaltung folgt, muss trotzdem nach dem Punkt ein Leerzeichen folgen, also:Text. <br>
.
Bei Abkürzungen tritt ebenfalls das Muster". "
auf. Um dieses zu "entschärfen", kann man z.B. schreiben
"BMW, VW, etc.<!-- --> steht für Automarken."
(nach 'Punkt' direktes Anschließen eines HTML-Kommentars) -
In Javadoc-Kommentaren zur Klassendeklaration sind folgende speziellen Tags (=Marke, Kennzeichen) nutzbar (siehe Beispiel):
-
@author Name und/oder E-Mail-Adresse, z.B.
@author Max Renkin, renkin@spengergasse.at
-
@version Datum und/oder Versionsnummer, z.B. 2021-01-09, v17
-
-
In Methoden-Dokumentation sollte verwendet werden:
-
@param paramName die Beschreibung dazu
, falls Parameter vorhanden (siehe Beispiel) -
@return die Beschreibung dazu
, falls nicht 'void' (siehe Beispiel) -
@throws ExceptionKlasse die Beschreibung der Exception
(Hinweis für später), die in der Methode "geplant" ausgelöst werden können
-
4.4.2. HTML5-Möglichkeiten
Die wichtigsten mit HTML5 gegebenen Möglichkeiten sind:
-
Zeilenschaltungen (auch mehrere) werden zu einem Leerzeichen umgewandelt.
-
Sichtbare Zeilenschaltungen erfolgen durch
<br>
. Üblicherweise (aber nicht zwingend) macht man danach auch eine Zeilenschaltung im Kommentar. -
Absätze werden durch
<p>Ein (meistens mehrzeiliger) Absatz ….</p>
erzeugt. Darin benötigte, zusätzliche, explizite Zeilenschaltungen erfolgen mit<br>
. -
Fettschrift wird durch
<b>Bold Text ... </b>
eingeschlossen -
Kursivschrift mit
<i>Italic Text ... </i>
-
Analog:
<kbd>
für Tastatureingabe-Markierung (Keyboard),<var>
für Variables,<code>
für Source Code),<samp>
für Beispiel-Ausgabe -
Links zu externen Informationsquellen erzeugt man mit z.B.
<a href="http://spengergasse.at">Die Spengergasse</a>
(a = anchor, 'Die Spengergasse' = angezeigter Link-Text). -
Auflistungen (ohne Nummerierung) schreibt man als "Unordered List" (ul) mit "ListItems" (li):
<ul> <li>Eintrag 1</li> <li>Eintrag 2</li> <li>…</li></ul>
(meist mehrzeilig - siehe Beispiel) -
Für nummerierte Aufzählungen wird
ul
durchol
(Ordered List) ersetzt. -
Aufzählungen können auch verschachtelt werden (wie in HTML üblich)
-
Tabellen beliebiger Komplexität sind möglich (Details siehe z.B. unten angeführte HTML-Dokumentation)
-
Es kann auch CSS und Javascript verwendet werden (Details siehe angeführte Links)
-
Bilder können auf verschiedene Arten eingebunden werden z.B. mit
<img src="https://www.spengergasse.at/wp-content/uploads/2020/04/SpengerLogo_720px_weiss_neu-e1586334374714.png" target="_blank">
(target="_blank"
zeigt Bild in neuem Tab/Fenster) -
Vektorgrafik kann sogar direkt eingebettet werden - z.B. mit:
<svg width="200" height="100"> <circle cx="150" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /> </svg>
Daraus entsteht:
Vekrorgrafik kann z.B. mit der Open-Source-Applikation https://inkscape.org/ erstellt und bearbeitet werden. Am besten als Standard-SVG speichern, dann kann aus dieser Datei der Code <svg> ... </svg>
direkt kopiert werden