Hilfe für MI-Erstis der Hochschule Flensburg

SProg-Hilfe

Einstieg

Java ist eine Programmiersprache und Entwicklungsumgebung. Bis heute erfreut sie sich einiger Beliebtheit, weil sie verhältnismäßig einfach ist und ein breites Anwendungsfeld abdecken kann.

Allgemein

Beim Programmieren schreibt man Quellcode. Dieser wird vom Compiler (Java Development Environment) in Bytecode umgewandelt, den der Computer verstehen kann. Damit bildet der programmierte Quellcode eine Schnittstelle zwischen Mensch und Maschine. Eine Java Virtual Machine entziffert dann den Bytecode für die einzelnen Betriebssysteme.

Java

Java kennt drei verschiedene Wortarten:

  • Schlüsselwörter: Dies sind in Java Wörter, deren Bedeutung genau im Programm festgelegt wurden, z.B. if, else, do.
  • Bezeichner: Dies sind Wörter, deren Bedeutung in Java vom Benutzer festgelegt werden, z.B. int zahl = 5;. zahl ist ein willkürlich vergebener Begriff des Programmierers für eine Variable.
  • Bezeichner der API: Auch bei diesen Begriffen steht die Bedeutung für Java schon fest, z.B. System.out.println().

Objekte, Attribute, Methoden und Klassen

In der Regel setzt sich ein Programm aus Objekten und Klassen zusammen. Dabei ist eine Klasse eine Art Bauplan für ein Objekt. Angenommen man schreibt ein Programm, dass Häuser bauen soll. Zuerst muss ein Bauplan für ein normales Haus erstellt werden. Dieses Haus hat bestimmte Eigenschaften, z.B. die Anzahl der Zimmer, Etagen oder die Farbe. Diese Eigenschaftstypen heißen in Java Attribute.

Die tatsächlichen Häuser, die wir mit dem Bauplan erbauen, sind dann die Objekte. Diese Häuser haben alle die selben Eigenschaftstypen, also Farbe, Zimmeranzahl, etc, aber die Eigenschaften selbst können sich unterscheiden. So kann ein Haus blau und das andere rot angestrichen sein, aber sie alle haben immer eine Farbe.

Würde man nun ein Haus mit einem Anbau bauen wollen, müsste man eine neue Klasse anlegen oder Vererbungsmechanismen nutzen.

Um so einen Bauplan zu strukturieren, benutzt man Methoden, die in einem Programm bestimmte Teilaufgaben erledigen. Eine Methode »erledigt« immer etwas.

Aufbau eines Skripts

Geschweifte Klammern {} schließen Codeabschnitte ein und schaffen so Struktur. Dabei umschließen sie bei Methoden den Methodenkörper (siehe 1) oder andere untergeordnete Abschnitte.

Der Beginn eines Abschnittes und das Ende (schließende Geschweifte Klammer) schließen auf derselben »Höhe« (vertikal betrachtet) im Code.

public class MeineKlasse {
  // Anfang Block 1
  public static void main(String[] args) {
    // Anfang Block 2
    int x = 10;
    int y = 4;

    if (x < y) {
      // Anfang Block 3
      System.out.println(x + " ist größer als " + y);
      // Ende Block 3
    }
    else {
      // Anfang Block 3
      System.out.println(y + " ist größer als " + x);
      // Ende Block 3
    }
    // Ende Block 2
  }
  // Ende Block 1
}

Rechnen

Ein Rechner heißt nicht umsonst so. Was Java letztendlich macht, ist, Dinge zu berechnen. Damit funktioniert es wie ein ganz normaler Taschenrechner. Man kann Zahlen mit Rechenzeichen verknüpfen und sich das Ergebnis ausgeben lassen.

int z.B. sagt dem Compiler, dass diese Variable ein Integer, also eine ganze Zahl, ist. Nach dem int folgt der Name der Variable. Der kann vom Programmierer beliebig gewählt werden, z.B. a. int z.B. sagt dem Compiler, dass diese Variable ein Integer, also eine ganze Zahl, ist. Nach dem int folgt der Name der Variable. Der kann vom Programmierer beliebig gewählt werden, z.B. a.

int a = 5;
int b = 3;
int c = (a + b) / 2; // ergibt 4

Java kann auch Variablen vergleichen.

<
kleiner als
>
größer als
==
ist gleich/entspricht
<=
kleiner gleich
>=
größer gleich
!=
ist nicht (Gegenteil von ist gleich)

Mit sogenannten Inkrement-Operatoren/Dekrement-Operatoren kann man einfach eine Eins auf eine Variable addieren, bzw. subtrahieren.

  • Präfix-Inkrement, z.B. zahl = ++a: a wird um eins erhöht und dann zahl hinzugefügt.
  • Postfix-Inkrement, z.B. zahl = a++: zahl bekommt den Wert von a, aber um eins erhöht wird a erst, nachdem diese Zeile abgeschlossen ist.

Rechnen am Beispiel

int x = 2;
int y = 5;
int z = 8;

x += 2;  // x = 4
y *= x;  // y = 20
z /= x;  // z = 2

Boolesche Verknüpfungen

Mit Booleschen Verknüpfungen lassen sich Aussagen bzw. Bedingungen untereinander in Beziehung setzen. Wenn Zahl a und Zahl b beide größer sind als 10, dann…

&&
UND – wahr, wenn beide Aussagen wahr sind
||
OR – wahr, wenn mindestens eine der Aussagen wahr ist
^
XOR – wahr, wenn nur eine der Aussagen wahr ist
!
NOT – negiert eine Aussage

Grundlagen der Pro­gram­mie­rung

Datentypen

Eine Variable in Java aufzuschreiben (zu initialisieren), sieht meist wie folgt aus:

// Datentyp Name Zuweisung Ausdruck
   int      zahl =         10      ;

In Java gibt es – wie in vielen anderen Programmiersprachen auch – Datentypen. Ein Datentyp sagt einer Variable, was sie ist. Beispielsweise kann eine Variable eine ganze Zahl, eine Zahl mit Kommastellen oder ein Wort sein. Im Folgenden eine Liste der wichtigsten primitiven Datentypen:

Integer
ganze Zahl – int a = 10;
Float
Fließkommazahl – float b = 3.5;
Double
Fließkommazahl (mit doppelt so viel Speicherplatz wie ein Float) – double c = 12e-3;
Character
einzelner Buchstabe – char d = 'h';
String
Wörter, Sätze, beliebige Zeichen – String e = "Moin!";

Ergebnisse in Java ausgeben – System.out.println()

Mit dem Befehl System.out.println() kann man das in der Konsole anzeigen lassen, was man in die Klammern – und dort in Anführungszeichen – schreibt. Das können ein paar selbst geschriebene Worte als String sein oder Variablen oder Ausdrücke.

System.out.println("Moin!"); // Console: Moin!
System.out.println(a + " ist größer"); // Console: 4 ist größer
System.out.println(name1 + " schlägt " + name2); // Console: Oliver schlägt Patrick

Wichtig ist, dass du die Worte, die du ausgeben lassen willst, in Anführungszeichen schreibt, aber nicht die Variablen!

Neben System.out.println() gibt es noch System.out.print(). Ersteres fügt am Ende einen Zeilenumbruch an (ln = line); Letzteres macht dies nicht.

System.out.println("Hallo");
System.out.print(", ");
System.out.print("Flensburg");

// Ausgabe:
// Hallo
// , Flensburg

Tipp: Bei den Ausgaben sollte man darauf achten, dass der Compiler nicht automatisch Leerzeichen setzt. Also setze sie im String, ansonsten »kleben« sie aneinander. → Hallo,Flensburg

Fallunterscheidungen

Häufig müssen beim Programmieren zwei Möglichkeiten miteinander verglichen werden. Wenn die Bedingung erfüllt ist, dann tue das; ansonsten tue etwas anderes.

// Wenn die Bedingung in den Klammern zutrifft, führe das aus,
// was in den geschweiften Klammern steht:
if (Bedingung) {
  // tue etwas
}
else {
  // tue etwas anderes
}

int a = 4;
int b = 6;
if (a < b) {
  System.out.println("b ist größer");
}
else {
  System.out.println("a ist größer");
}

Tipp: Achte auf die geschweiften Klammern!

Manchmal kann man ein if else auch einfacher schreiben. Schaue dir den folgenden Code einmal an:

int a = 4;
int x;

if (a < 6) {
  x = 0;
}
else {
  x = 1;
}

Es handelt sich um eine einfache Abfrage. Beide Fälle setzen x auf einen Wert, mehr nicht. Etwas Derartiges auf diese Weise aufzuschreiben, erfordert verhältnismäßig viel Aufwand. Es gibt dafür aber einen einfacheren Weg:

int a = 4;
int x = a < 6 ? 0 : 1;

Der sogenannte ternary operator ist nach dem Schema

Bedingung ? wennBedingungTrue : wennBedingungFalse

aufgebaut. Ergibt die Bedingung true, wird der Wert zurückgegeben, der direkt hinter dem ? steht, wenn sie false ergibt, wird der Wert zurückgegeben, der hinter dem : steht. Den zurückgegebenen Wert kann man dann zum Beispiel direkt in einer Variablen speichern.

Als Alternative zu if else gibt es noch switch. Damit kannst du eine Variable auf bestimmte Werte überprüfen und darauf basierend verschiedene Schritte ausführen. Ein einfaches switch sieht wie folgt aus:

switch (test) {
  case 1:
    System.out.println("test ist 1");
    break;
  case 2:
    System.out.println("test ist 2");
    break;
  default:
    System.out.println("test ist etwas anderes");
    break;
}

test ist hier vom Typ int. Wenn test == 1, wird "test ist 1" ausgegeben; wenn test == 2, wird "test ist 2" ausgegeben. Der default case funktioniert wie ein else.

Beachte: Das break; ist erforderlich!

while- und do-while-Schleife

Die while-Schleife wiederholt das, was in ihr steht. Am Anfang steht eine Bedingung und solange die zutrifft, wird das, was in den geschweiften Klammern steht, wiederholt.

Die do while-Schleife führt das, was in ihr steht, zunächst aus, ohne die gegebene Bedingung zu überprüfen. Danach führt sie wie eine while-Schleife fort.

int a = 0;
int b = 6;

while (a < b) { // Solange a kleiner als b ist,
  a++;          // wird a um eins erhöht
}

// ODER

do {              // Mache folgendes:
  a++;            // erhöhe um eins
} while (a < b);  // sofort und danach solange a kleiner als b ist

for-Schleife

Die for-Schleife macht dasselbe wie die while-Schleife, nur ausführlicher.

for (variableInitialisieren; Bedingung; Operation){
  // tue etwas
}


int b = 5;

//   1. Integer a sei 0;  2. Wenn a kleiner ist als b:  4. Erhöhe a um eins
for (int a = 0;           a < b;                        a++                ) {
  System.out.println(a); // 3. Gebe a aus
}
// Das wird solange ausgeführt, bis die Bedingung nicht mehr wahr ist, d.h., bis a=5 ist.

Beim ersten Durchlauf ist a also 0; am Ende dessen wird a um eins erhöht, was bedeutet, dass a beim zweiten Durchlauf 1 ist, usw.

Arrays

Arrays braucht man, um mehrere gleichartige Dinge zu speichern. Um genau zu sein, ist ein Array eine statische Datenstruktur, d.h. man legt anfangs fest, wie viele »Speicherplätze« man braucht und legt dann in jeden Speicherplatz ein Element rein. Grundsätzlich kann man sich das wie ein Regal mit beliebig vielen gleich großen Fächern vorstellen.

Erzeugen eines Arrays

// Datentyp Array    Name      Zuweisung    new Datentyp  Größe
   int      []       meinArray =	    new int      [5    ]  ;

Wenn man ein Array später mit ganzen Zahlen füllen möchte, nimmt man einen Integer. Die eckigen Klammern zeigen an, dass es sich um ein Array handelt. (Würde man sie vergessen hätte man einen simplen Integer mit dem Namen meinArray, was natürlich sinnfrei ist.)

Füllen eines Arrays bei der Erzeugung

String[] namenListe = { "Joscha", "Max", "Julia", "Leif", "Marie" };

// ---------------------------------------
// | Joscha | Max | Julia | Leif | Marie |
// ---------------------------------------

Hier füllen wir ein Array, in das nur Strings sollen, mit Namen. Die Größe des Arrays wird automatisch von der Anzahl der Elemente in den geschweiften Klammern festgelegt: Fünf Strings, fünf Stellen im Array.

Beachte, dass bei einem Array aus Strings alle Wörter in Anführungszeichen stehen müssen.

Füllen eines Arrays per Zuweisung

int[] neuesArray = new int[5]; // Fünf Speicherplätze, von 0 bis 4
neuesArray[2] = 32;            // Die dritte Stelle des Arrays wird mit 32 gefüllt

Füllen eines Arrays per for-Schleife

int[] meinArray = new int[5];
int a = 6;
for (int x = 0; x < 5; x++) {
  meinArray[x] = ++a;
}

Oft werden Arrays erst erzeugt und erst später mit einer for-Schleife befüllt.

Beachte, dass der Index eines Arrays bei 0 anfängt, nicht bei 1! Daher definieren wir x = 0 zu Beginn der Schleife. Das heißt, beim ersten Durchlauf steht gewissermaßen meinArray[0] = ++a;, was die erste Stelle im Array darstellt. Da wir a um eins erhöhen, bevor es zugewiesen wird, setzen wir an die erste Stelle des Arrays eine 7.

Beim zweiten Durchlauf ist x = 1. Das entspricht der zweiten Stelle im Array. Durch die Erhöhung wird a zu 8.

Die Schleife bricht ab, wenn die Bedingung x < 5 nicht mehr zutrifft. Beim letzten Durchlauf gilt daher x = 4, was der fünften Stelle im Array entspricht.

Strings

In diesem Abschnitt werden wir uns damit auseinandersetzen, wie Strings funktionieren und wie man sie einsetzt.

  • Strings direkt vergleichen

    String vorname = "Leif";
    String nachname = "Leif";
    vorname == nachname; // true
  • Strings per Methode vergleichen

    if (vorname.equals(nachname)) {
      System.out.println("Sie sind gleich");
    }
  • Einzelne Buchstaben von Strings ausgeben

    int a = 1;
    char x = vorname.charAt(1);
    System.out.println("Das Wort " + vorname + " hat an der Stelle " + a + " den Buchstaben " + x);
    // Console: Das Wort Leif hat an der Stelle 1 den Buchstaben e
  • In Strings kann man auch Zahlen speichern. Damit diese später aber als solche erkannt werden können, muss man sie »parsen«.

    String str = "3456";
    int zahl = Integer.parseInt(str);
    // ODER
    double zahl = Double.parseDouble(str);

Methoden

Methoden werden genutzt, um ein Programm zu strukturieren. Diese Methoden stehen in Klassen und in ihnen werden mehrere Anweisungen zusammengefasst. Wird eine Methode an anderer Stelle aufgerufen, werden die Anweisungen darin ausgeführt.

Zuerst muss eine Methode angelegt werden.

// Modifikatoren Rückgabetyp Name        (Typ Parameter, weitere Parameter)
   public        int         meineMethode(int x        , int y            ) {
     int z = x * y;
     return z; // gibt einen Integer zurück
   } // Geschweifte Klammern schließen Methode ab

Nur die main-Methode wird vom Compiler gestartet. In ihr befinden sich die Aufrufe zu meineMethode und ausgeben.

public class Projektmanagement {

  public static void main(String args[]) {
    int x = 2;
    int y = 6;
    int ergebnis;

    ergebnis = meineMethode(x, y);
  }

  static int meineMethode(int x, int y) {
    int z;
    z = x * y;
    return z;
  }

  static void ausgeben(int ergebnis) {
    System.out.println(ergebnis);
  }

}

Das, was meineMethode zurückgibt, wird in ergebnis gespeichert.

public class Projektmanagement {

  public static void main(String args[]) {
    int x = 2;
    int y = 6;
    int ergebnis;

    ergebnis = meineMethode(x, y);
  }

  static int meineMethode(int x, int y) {
    int z;
    z = x * y;
    return z;
  }

  static void ausgeben(int ergebnis) {
    System.out.println(ergebnis);
  }

}

void heißt nicht umsonst »leer«: Diese Methode gibt keinen Wert zurück; es gibt also auch kein return. Sobald aber ein Rückgabetyp festgelegt wurde, ist return verpflichtend. void wird anstelle des Rückgabetyps geschrieben, wenn man keinen benötigt.

Modifikatoren

Diese Modifikatoren verändern die Eigenschaften von Methoden (oder Attributen einer Klasse) und werden vor den Rückgabetyp geschrieben.

static
Die Methode ist an kein Objekt gebunden. Die Methode existiert nur einmal und ab Programmstart. Sie kann nicht auf Objektattribute zugreifen (wohl aber auf Attribute, die auch mit static definiert wurden). Attribute, die so erstellt wurden, exisitieren auch nur einmal und ab Programmstart – es muss also kein Objekt erstellt worden sein, um auf ein statisches Attribut oder eine statische Methode zugreifen zu können.
public
Andere Klassen (anderer Packages) können auf diese Methode zugreifen. (Bis jetzt arbeiten wir noch nicht klassenübergreifend. Das kann uns vorerst egal sein. ⇒ Objektorientierte Programmierung)

Weitere Eigenschaften von Methoden

  • Methoden können mit Ausdrücken aufgerufen werden

    int test = 4 * summiere(12, 4);
  • Methoden können Ausdrucke als Parameter benutzen

    int test = summiere(x, y * 2);

Struk­tur­ier­tes Pro­gram­mie­ren – Klas­sen

Eine Klasse ist ein Bauplan für ein Objekt. In ihr werden Variablen und Methoden gespeichert, mit deren Hilfe später die Objekte (= Instanzen einer Klasse) erzeugt werden.

Sei beispielsweise Auto eine Klasse, dann wäre R4 ein konkretes Objekt dieser Klasse.