Zur Haupt­na­vi­ga­ti­on sprin­gen [Alt]+[0] Zum Sei­ten­in­halt sprin­gen [Alt]+[1]

Tech­ni­sche Hin­ter­grün­de zur Pro­gram­mier­spra­che Java

Zur Um­set­zung der Bil­dungs­stan­dards wird in die­sem Ma­te­ri­al aus­schließ­lich die Pro­gram­mier­spra­che Java ver­wen­det. Für das Ver­ständ­nis ge­ne­ri­scher Pro­gram­mie­rung und Samm­lun­gen in Java wird zu­nächst auf Pro­gram­mier­pa­ra­dig­men im all­ge­mei­nen und an­schlie­ßend auf die Um­set­zung in Java ein­ge­gan­gen. Um die Funk­ti­ons­wei­se ge­ne­ri­scher Da­ten­ty­pen und Lamb­da­aus­drü­cke nach­zu­voll­zie­hen, wird auf die Ty­pi­sie­rung in Java und Schnitt­stel­len näher ein­ge­gan­gen.

Pro­gram­mier­pa­ra­dig­men

Programmierparadigmen

Ab­bil­dung 1: Pro­gram­mier­pa­ra­dig­men ZPG In­for­ma­tik [CC BY-SA 4.0 DE], aus 01_hin­ter­grund.pdf

Es gibt ver­schie­de­ne grund­le­gen­de Prin­zi­pi­en der Pro­gram­mie­rung, die als Programmier­paradigmen be­zeich­net wer­den4 . Hier­zu ge­hö­ren auch struk­tu­rier­te und ob­jekt­ori­en­tier­te Pro­gram­mie­rung. Jedes Pa­ra­dig­ma for­dert be­stimm­te sprach­li­che Mit­tel und stellt Al­go­rith­men durch ver­schie­de­ne No­ta­ti­ons­for­men dar. Durch die in einer Programmier­sprache zur Ver­fü­gung ste­hen­den sprach­li­chen Mit­tel, wird das Pro­gram­mie­ren nach einem oder meh­re­ren Pa­ra­dig­men er­mög­licht oder aus­ge­schlos­sen.

Java ist eine struk­tu­rier­te, ob­jekt­ori­en­tier­te, mo­du­la­re Pro­gram­mier­spra­che, die zudem ge­ne­ri­sche Pro­gram­mie­rung er­mög­licht und Ele­men­te funk­tio­na­ler Pro­gram­mie­rung be­reit stellt.

Pa­ra­dig­ma Sprach­li­che Mit­tel No­ta­ti­ons­for­men / Bei­spie­le
Im­pe­ra­ti­ve Pro­gram­mie­rung Zu­wei­sun­gen (Spei­cher­va­ria­blen), Kon­troll­struk­tu­ren: Schlei­fen

Nassi-Sh­nei­der­man-Dia­gram­me/Struk­to­gram­me

As­sem­bler

Pro­ze­du­ra­le Pro­gram­mie­rung Les­bar be­nann­te Teil­pro­gram­me/Pro­ze­du­ren, Daten und Ob­jek­te ver­ar­bei­ten­de Pro­ze­du­ren ge­trennt; C, Pas­cal

Ob­jekt­ori­en­tier­te Pro­gram­mie­rung

Ob­jek­te mit Daten und dar­auf ar­bei­ten­den Me­tho­den als eine Ein­heit.

UML Dia­gram­me: z.B. Klas­sen­dia­gram­me, Ob­jekt­dia­gram­me

Java, Py­thon,Snap!, Scratch

De­kla­ra­ti­ve Pro­gram­mie­rung Kon­troll­struk­tu­ren: Re­kur­si­on und Sub­sti­tu­ti­on („Auf­ruf“) SQL
Funk­tio­na­le Pro­gram­mie­rung

Be­schrei­bung durch Funk­tio­nen (mit Funk­ti­ons­va­ria­blen) die auf Daten ar­bei­ten.

Lis­ten (map-fil­ter-re­du­ce), Lamb­da, Clo­sures

Ob­jek­te wer­den nicht ver­än­dert, son­dern neu er­stellt.

Be­güns­tigt Par­al­le­li­sie­rung

Teile von UML: Ak­ti­vi­täts­dia­gram­me, Zu­stands­dia­gram­me

LISP-ba­sier­te Spra­chen, EC­MA­Script (Java-Script)

teils in Java: Funk­tio­na­le In­ter­faces, Lamb­da­aus­drü­cke

Mo­du­la­re Pro­gram­mie­rung

Mo­du­le

Bei OOP: ADTs (Daten und Funk­tio­nen zur Be­hand­lung die­ser Daten als Ein­heit)

Struk­tu­rier­te Pro­gram­mie­rung

Les­ba­rer Code durch Kon­troll­struk­tu­ren: Se­quenz, Ver­zwei­gung, Schlei­fen

Gül­tig­keits­be­reich von Va­ria­blen (Scope)

Ge­ne­ri­sche Pro­gram­mie­rung

Al­go­rith­men für meh­re­re Da­ten­ty­pen ver­wend­bar ma­chen.

Ge­ne­ri­sche Da­ten­ty­pen

In Java: Collec­tions Frame­work

Ta­bel­le 1: Aus­wahl an Pro­gram­mier­pa­ra­dig­men und ihrer sprach­li­chen Mit­tel/No­ta­ti­ons­for­men; The­men aus dem Bil­dungs­plan 2016 sind fett her­vor­ge­ho­ben

Ty­pi­sie­rung

Jeder Aus­druck in einem Java Pro­gramm er­gibt ent­we­der kein Er­geb­nis (void) oder einen Wert eines Typs, der zur Lauf­zeit ab­ge­lei­tet wer­den kann. Ein Aus­druck muss mit dem Typ des Kon­texts, in dem er er­scheint (Ziel­typ), kom­pa­ti­bel sein. An­sons­ten kommt es zu einem Kom­pi­lie­rungs­feh­ler. Der Typ eines Aus­drucks kann ab­hän­gig vom Ziel­typ sein, das heißt je nach Kon­text, in dem der selbe Aus­druck vor­kommt, wird vom Com­pi­ler ein an­de­rer Typ er­mit­telt („ab­ge­lei­tet“). Das „+“ kann zum Bei­spiel je nach Kon­text die Ad­di­ti­on von z.B. In­te­ger-Wer­ten oder die Kon­ka­te­na­ti­on von String-Wer­ten be­deu­ten. Man spricht von:

  • Typ­in­fe­renz: Typen wer­den ent­spre­chend ihrem Ziel­typ au­to­ma­tisch ab­ge­lei­tet.
  • Ty­pum­wand­lung: Stimmt der Typ des Aus­drucks nicht mit dem Ziel­typ über­ein, kann manch­mal ohne Kom­pi­lie­rungs­feh­ler eine im­pli­zi­te Um­wand­lung in den Ziel­typ statt fin­den.
  • Typ­kon­ver­tie­rung: Der Ziel­typ kann vom Pro­gram­mie­rer z.B. mit dem „type cast“-Ope­ra­tor ex­pli­zit vor­ge­ge­ben wer­den. Bei Ab­wei­chung vom Ziel­typ fin­det eine ex­pli­zi­te Um­wand­lung in den Ziel­typ statt.
  • Typ­de­kla­ra­ti­on: Der Kon­text man­cher Aus­drü­cke kann de­fi­niert wer­den. So wird bei der De­kla­ra­ti­on einer Va­ria­ble oder eines Pa­ra­me­ters der Ziel­typ für jedes wei­te­re Vor­kom­men des Aus­drucks fest­ge­legt und dann durch Typ­in­fe­renz ab­ge­lei­tet.

Bei man­chen Ty­pum­wand­lun­gen fin­den Ty­p­über­prü­fun­gen oder Ty­p­über­set­zun­gen erst zur Lauf­zeit statt. Kommt es dabei zu einem Lauf­zeit­feh­ler, wird eine Aus­nah­me (engl. ex­cep­ti­on) ge­wor­fen.

Eine ge­naue Be­schrei­bung mög­li­cher Aus­drü­cke, Kon­tex­te, Typen und Um­wand­lun­gen bie­tet die Java® Lan­gua­ge Spe­ci­fi­ca­ti­on5 .

Eine Ty­pum­wand­lung kann er­wei­ternd (engl. wi­de­ning) oder ein­schrän­kend (engl. nar­ro­wing) sein. Bei einer er­wei­tern­den Um­wand­lung geht si­cher keine In­for­ma­ti­on ver­lo­ren, die Um­wand­lung kann im­pli­zit statt fin­den. Bei einer ein­schrän­ken­den Um­wand­lung kann In­for­ma­ti­on ver­lo­ren gehen, hier muss eine ex­pli­zi­te Kon­ver­tie­rung vor­ge­nom­men wer­den.

Bei­spiel:

int i = 12.5f;	// einschränkend, weil 12.5 nicht verlustfrei als
	// int dargestellt werden kann → Kompilierungsfehler
int i = (int)12.5f;	// explizite einschränkende Typumwandlung;
	// 12.5 wird auf 12 abgeschnitten.
float f = i;	// implizite erweiternde Typumwandlung, weil jeder int-	// Wert verlustfrei als float dargestellt werden kann.

Bei pri­mi­ti­ven Da­ten­ty­pen fin­det eine Ty­pum­wand­lung nach in der Sprach­spe­zi­fi­ka­ti­on de­fi­nier­ten Re­geln statt. Bei der Um­wand­lung von Re­fe­renz-Typen muss eine Ver­wandt­schaft ge­ge­ben sein. Als Aus­nah­me sind hier in Java le­dig­lich die Um­wand­lung pri­mi­ti­ver Typen in einen String-Typ mög­lich sowie das so ge­nann­te Au­to­boxing, also die Um­wand­lung pri­mi­ti­ven Zahl­da­ten­ty­pen (int, short usw) in eine In­stanz der je­wei­li­gen Wrap­per-Klas­se (bspw. int zu In­te­ger).

Bei­spiel:

String s = "Die Zahl lautet " + i; // Umwandlung int nach String
Integer intObjekt = i; // Autoboxing: Umwandlung int nach Integer

Bei Re­fe­renz­ty­pen ist eine Um­wand­lung er­wei­ternd, wenn die Um­wand­lung von einem Sub­typ in die Su­per­klas­se ge­schieht. Die Um­wand­lung von Re­fe­renz­ty­pen in ihren Ba­sis­typ Object ist immer mög­lich. Eine Um­wand­lung ist ein­schrän­kend, wenn sie aus Sicht einer Su­per­klas­se in die er­wei­ter­te Klas­se er­fol­gen soll. Vor allem die ein­schrän­ken­de Kon­ver­tie­rung von Re­fe­renz­ty­pen birgt die Ge­fahr von Lauf­zeit­feh­lern. Es ist dann oft eine Aus­nah­me­be­hand­lung im Code not­wen­dig.

Im Kon­text von Me­tho­den wird der Ziel­typ für for­ma­le Pa­ra­me­ter bei der De­kla­ra­ti­on an­ge­ge­ben. Beim Me­tho­den­auf­ruf ist der Ziel­typ dann durch Typ­in­fe­renz fest­ge­legt. In Ta­bel­le 2 sind ei­ni­ge Fach­be­grif­fe im Me­tho­den­kon­text fest­ge­legt, wie sie in die­sem Do­ku­ment ver­wen­det wer­den.

Wich­tig zu er­wäh­nen ist, dass in Java Ar­gu­men­te immer nach dem Prin­zip Pass-By-Value über­ge­ben wer­den, dass heißt es wird immer eine Kopie des kon­kre­ten Ar­gu­men­tes an die Me­tho­de über­ge­ben. Das Ori­gi­nal im auf­ru­fen­den Kon­text kann nicht durch die Me­tho­de ge­än­dert wer­den. Dies gilt auch für Re­fe­renz­ty­pen. Hier wird al­ler­dings eine Kopie der Re­fe­renz über­ge­ben6. Man könn­te das Prin­zip daher auch Pass-Re­fe­rence-By-Value nen­nen.

Fachbegriffe zu Wertparametern in Methoden

Ta­bel­le 2: Fach­be­grif­fe zu Wert­pa­ra­me­tern in Me­tho­den von ZPG In­for­ma­tik [CC BY-SA 4.0 DE], aus 01_hin­ter­grund.pdf

Ta­bel­le 2: Fach­be­grif­fe zu Wert­pa­ra­me­tern in Me­tho­den

Schnitt­stel­len – In­ter­faces

Im All­ge­mei­nen stellt eine Schnitt­stel­le eine nach außen be­kann­te Be­schrei­bung einer Black­box dar, über die mit der Black­box kom­mu­ni­ziert wer­den kann. Es ist dabei un­er­heb­lich, wie diese Black­box in­tern In­for­ma­tio­nen ver­ar­bei­tet. So de­fi­niert die Java-Spe­zi­fi­ka­ti­on in Mo­du­le und Pa­ke­te un­ter­glie­der­te Pro­gram­mier­schnitt­stel­len (API: engl. ap­p­li­ca­ti­on pro­gramming in­ter­face). Das Collec­tions-Frame­work ist zum Bei­spiel Teil des Pak­tes java.util, des Mo­duls java.base und be­schreibt neben kon­kre­ten, wie abs­trak­te Klas­sen auch Al­go­rith­men7. In der ob­jekt­ori­en­tier­ten Pro­gram­mie­rung gibt eine Schnitt­stel­le an, wel­che Me­tho­den in einer Klas­se vor­han­den sind, bzw. bei der Im­ple­men­tie­rung vor­han­den sein müs­sen. Knapp ge­sagt eine Schnitt­stel­le ist der pu­blic-Teil einer Klas­se.

Die Pro­gram­mier­spra­che Java bie­tet mit dem sprach­li­chen Mit­tel eines Interface eine Mög­lich­keit eine sol­che Schnitt­stel­le zu de­fi­nie­ren. Im Eng­li­schen ist der Be­griff für eine all­ge­mei­ne Schnitt­stel­le (im Sinne des pu­blic-Teils einer Klas­se) der selbe wie für das sprach­li­che Mit­tel. Im Deut­schen lässt sich dies je­doch dif­fe­ren­zie­ren. In die­sem Do­ku­ment wird für das sprach­li­che Mit­tel der Be­griff In­ter­face ver­wen­det, an­sons­ten der Be­griff Schnitt­stel­le.

In­ter­faces er­mög­li­chen es dem Pro­gram­mie­rer, so wie er es mit Klas­sen tut, selbst Typen zu de­fi­nie­ren. In­ter­faces geben wie abs­trak­te Klas­sen die mi­ni­ma­le Typ­si­gna­tur für alle Sub­ty­pen vor, mit dem Un­ter­schied selbst keine Im­ple­men­tie­rung (Aus­nah­me: static und default Me­tho­den)8 zu be­sit­zen. Von einem In­ter­face kann wie von einer abs­trak­te Klas­sen keine In­stanz er­zeugt wer­den.

Ein In­ter­face wird wie folgt de­kla­riert:

Modifikator interface Schnittstelle
{
    final Typ konstante = Wert;
    Modifikator Rückgabetyp methode( Parameterliste );
}

Das In­ter­face be­sitzt nur Me­tho­den­si­gna­tu­ren und Kon­stan­ten. Bei den Me­tho­den kann der Mo­di­fi­ka­tor sta­tic oder de­fault sein. Die Me­tho­den sind au­to­ma­tisch pu­blic, pri­va­te ist nicht er­laubt.

Um einen Sub­typ zu de­kla­rie­ren geht man wie folgt vor:

Modifikator class Klasse extends Superklasse implements Schnittstelle
{
    public Rückgabetyp methode( Parameterliste )
    {
        // Anweisungen
    }
}

Mit dem Schlüs­sel­wort implements wird an­ge­ge­ben, wel­che In­ter­faces die Klas­se im­ple­men­tiert. Dies kön­nen an­ders als beim Er­wei­tern einer Klas­se, auch meh­re­re sein (mit Komma ge­trennt hin­ter­ein­an­der auf­ge­lis­tet). Im­ple­men­tiert eine Klas­se ein In­ter­face, muss sie alle Me­tho­den, die von der Schnitt­stel­le vor­ge­ge­ben sind, im­ple­men­tie­ren. Diese sind per De­fi­ni­ti­on public. Es kann hier­bei nicht zu Kon­flik­ten kom­men, da jedes In­ter­face nur Si­gna­tu­ren und keine Im­ple­men­tie­run­gen vor­gibt.

In­ter­faces kön­nen auch, wie Klas­sen, eine Ver­er­bungs­hier­ar­chie be­sit­zen. Dort gel­ten die sel­ben Re­geln wie bei Klas­sen.

Der große Vor­teil von In­ter­faces liegt darin, dass sie fle­xi­bler („Mehr­fach­im­ple­men­tie­rung“) als abs­trak­te Klas­sen („keine Mehr­fach­ver­er­bung“) sind und damit bes­tens ge­eig­net einen Ziel­typ mit kla­rer Mi­ni­mal­si­gna­tur vor­zu­ge­ben. Al­ler­dings muss die kom­plet­te Si­gna­tur im Ge­gen­satz zur Er­wei­te­rung abs­trak­ter Klas­sen bei der Im­ple­men­tie­rung eines In­ter­faces er­neut auf­ge­schrie­ben wer­den. Als Er­satz für abs­trak­te Klas­sen sind In­ter­faces daher nicht ge­dacht.

Für das Ver­ständ­nis ge­ne­ri­scher Samm­lun­gen und Lamb­da­aus­drü­cke ist es un­ver­zicht­bar, im Un­ter­richt In­ter­faces zu the­ma­ti­sie­ren, auch wenn diese nicht ex­pli­zit im Bil­dungs­plan er­wähnt wer­den. Für die Schü­le­rin­nen und Schü­ler ist es aber kein wei­ter Weg, In­ter­faces zu ver­ste­hen. Im Un­ter­richts­ver­lauf müs­sen sie le­dig­lich In­ter­faces als Ziel­typ iden­ti­fi­zie­ren und selbst keine de­fi­nie­ren oder im­ple­men­tie­ren.

 

4https://​www.​it­wis­sen.​info/​Pro​gram​mier​para​digm​a-​pro­gramming-​pa­ra­digm.​html (aus­ge­wer­tet am 22.12.2020)

5 https://​docs.​ora­cle.​com/​ja­va­se/​specs/​jls/​se11/​html/​jls-​15.​html (aus­ge­wer­tet am 22.12.2020)

6 Eine gute Er­klä­rung für Pass-Re­fe­rence-By-Value: https://​www.​code­ja­va.​net/​java-​core/​the-​java-​lan­gua­ge/​java-​va­ria­bles-​pas­sing-​ex­am­ples-​pass-​by-​value-​or-​pass-​by-​re­fe­rence (aus­ge­wer­tet 3.2.2021)

7 https://​docs.​ora­cle.​com/​en/​java/​ja­va­se/​11/​docs/​api/​java.​base/​java/​util/​doc-​files/​coll-​re­fe­rence.​html (aus­ge­wer­tet 3.2.2021)

8 De­fault-Me­tho­den er­mög­li­chen Rück­wärts­kom­pa­ti­bi­li­tät, Sta­tic-Me­tho­den wer­den wie sta­ti­sche Me­tho­den in re­gu­lä­ren Klas­sen mit dem In­ter­face an­statt einem Ob­jekt as­so­zi­iert und daher von allen Ob­jek­ten die das In­ter­face im­ple­men­tie­ren ge­teilt. Auf beide wird hier nicht wei­ter ein­ge­gan­gen. Für eine ge­naue­re Be­schrei­bung mit Bei­spie­len siehe https://​docs.​ora­cle.​com/​ja­va­se/​tu­to­ri­al/​java/​IandI/​def​ault​meth​ods.​html (aus­ge­wer­tet am 3.2.2012)

 

Hin­ter­grund­in­for­ma­tio­nen: Her­un­ter­la­den [odt][370 KB]

Hin­ter­grund­in­for­ma­tio­nen: Her­un­ter­la­den [pdf][480 KB]

 

Wei­ter zu Ge­ne­ri­sche Da­ten­ty­pen