Grundlegende Begriffe der Programmierung – Codebeispiele in Java.
Basisbegriffe rund um Programme und ihre Ausführung
Anweisungen, die ein Computer ausführt
Für Menschen lesbarer Text eines Programms
.java-Dateien// Datei: HalloWelt.java
public class HalloWelt {
public static void main(String[] args) {
System.out.println("Hallo Welt!");
}
}
Schreibregeln einer Programmiersprache
int zahl = 5; // korrekte Syntax
int zahl = 5 // Syntaxfehler: Semikolon fehlt
Übersetzt den gesamten Code vor der Ausführung
javac → Bytecode (.class) → Ausführung in der JVM (Java Virtual Machine)javac HalloWelt.java → erzeugt HalloWelt.class
java HalloWelt → führt das Programm in der JVM aus
Führt Code direkt während der Laufzeit aus
| Compiler | Interpreter | |
|---|---|---|
| Übersetzung | vorab, komplett | zur Laufzeit, schrittweise |
| Ergebnis | ausführbare Datei / Bytecode | keine Datei, direkte Ausführung |
| Fehlererkennung | vor dem Start | erst beim Ausführen der Zeile |
| Ausführung | meist schneller | meist langsamer |
python hallo.py → Interpreter führt den Quellcode direkt aus
java HalloWelt → JVM interpretiert Bytecode (+ JIT-Compiler)
Programmierparadigma: grundlegender Programmierstil / Denkweise
Programm als Abfolge von Befehlen
int summe = 0;
for (int i = 1; i <= 3; i++) {
summe += i;
}
Programm aufgeteilt in Prozeduren
static int summe(int[] zahlen) {
int s = 0;
for (int z : zahlen) s += z;
return s;
}
Programm aus zusammenarbeitenden Objekten
Konto k = new Konto();
k.einzahlen(100);
Programm aus reinen Funktionen
int summe = List.of(1, 2, 3).stream()
.mapToInt(z -> z)
.sum();
Beschreiben, was gewünscht ist
SELECT name FROM kunden WHERE ort = 'Berlin';
Speichern und Verwalten von Werten
Benannter Behälter für einen Wert
int alter = 30;
alter = 31; // Wert ändert sich
Wert, der sich nie ändert
finalfinal double PI = 3.14159;
// PI = 3; → Compilerfehler
public static final int MAX_BENUTZER = 100; // Klassenkonstante
Art eines Werts
byte, short, int, long, float, double, char, booleanString)int anzahl = 42;
double preis = 19.99;
boolean aktiv = true;
char zeichen = 'A';
String name = "Anna"; // Referenztyp
Wie streng eine Sprache Typen prüft
int x = "5"; // Java: Compilerfehler, String ist kein int
int y = Integer.parseInt("5"); // explizite Umwandlung nötig
// Zum Vergleich JavaScript (schwach typisiert):
// "5" * 2 → 10 (String wird still in eine Zahl umgewandelt)
Variable anlegen
int zaehler; // Deklaration
String name;
Variable den ersten Wert geben
int zaehler; // Deklaration
zaehler = 0; // Initialisierung
int summe = 0; // Deklaration + Initialisierung
Wo eine Variable gilt
{ }public void beispiel() {
int a = 1; // gültig in der ganzen Methode
if (a > 0) {
int b = 2; // nur im if-Block gültig
System.out.println(a + b);
}
// System.out.println(b); → Fehler: b ist hier unbekannt
}
Wert in einen anderen Typ umwandeln
int ganz = 10;
double komma = ganz; // implizit: 10 → 10.0
double wert = 9.87;
int abgeschnitten = (int) wert; // explizit: 9.87 → 9 (Nachkommastellen weg)
String text = String.valueOf(42); // Zahl → String
int zahl = Integer.parseInt("42"); // String → Zahl
Programmablauf steuern und Code strukturieren
Rechnen, vergleichen, verknüpfen
+, -, *, /, % (Rest)==, !=, <, >, <=, >= → Ergebnis boolean&& (UND), || (ODER), ! (NICHT)=, +=, -=, ++, --int a = 7, b = 3;
int rest = a % b; // 1
boolean groesser = a > b; // true
boolean beide = a > 0 && b > 0; // true
a += 2; // a ist jetzt 9
if / else)Verzweigung abhängig von einer Bedingung
true ausführenelse if / else für weitere Fälleint note = 2;
if (note == 1) {
System.out.println("Sehr gut");
} else if (note <= 3) {
System.out.println("Bestanden");
} else {
System.out.println("Nicht bestanden");
}
Code wiederholt ausführen
for: bekannte Anzahl Durchläufewhile: Prüfung vor jedem Durchlaufdo-while: Prüfung nach dem Durchlauf → mind. 1 Durchlaufforeach: alle Elemente einer Sammlungfor (int i = 0; i < 3; i++) {
System.out.println(i); // 0, 1, 2
}
int x = 0;
while (x < 3) {
x++;
}
do {
x--;
} while (x > 0);
String[] namen = {"Anna", "Ben"};
for (String n : namen) {
System.out.println(n);
}
break / continueSchleifenablauf gezielt steuern
break: Schleife sofort beendencontinue: aktuellen Durchlauf überspringen → nächster Durchlauffor (int i = 0; i < 10; i++) {
if (i == 5) break; // Schleife endet bei 5
if (i % 2 == 0) continue; // gerade Zahlen überspringen
System.out.println(i); // 1, 3
}
returnMethode verlassen, Ergebnis liefern
public int doppelt(int zahl) {
return zahl * 2;
}
public void pruefe(int wert) {
if (wert < 0) return; // vorzeitiger Ausstieg, ohne Rückgabewert
System.out.println("Wert ok");
}
Benannter, aufrufbarer Codeblock
public class Rechner {
public int addiere(int a, int b) {
return a + b;
}
}
Platzhalter vs. übergebener Wert
public void begruesse(String name) { // name = Parameter
System.out.println("Hallo " + name);
}
begruesse("Anna"); // "Anna" = Argument
Ergebnis einer Methode
void = kein Rückgabewertpublic double flaeche(double breite, double hoehe) { // Rückgabetyp double
return breite * hoehe;
}
double f = flaeche(2.0, 3.5); // f = 7.0
Gleicher Name, verschiedene Parameter
public int addiere(int a, int b) { return a + b; }
public int addiere(int a, int b, int c) { return a + b + c; }
public double addiere(double a, double b) { return a + b; }
addiere(1, 2); // erste Variante
addiere(1, 2, 3); // zweite Variante
addiere(1.5, 2.5); // dritte Variante
Programmieren mit Klassen und Objekten
Bauplan für Objekte
public class Auto {
String marke;
int ps;
void fahren() {
System.out.println(marke + " fährt.");
}
}
Konkretes Exemplar einer Klasse
newAuto meinAuto = new Auto();
meinAuto.marke = "VW";
meinAuto.fahren(); // "VW fährt."
Anderes Wort für Objekt
a1 ist eine Instanz von Auto“Auto a1 = new Auto(); // Instanz 1
Auto a2 = new Auto(); // Instanz 2, unabhängig von a1
Eigenschaft eines Objekts
static)public class Person {
private String name; // Attribut
private int alter; // Attribut
}
Fähigkeit eines Objekts
public class Konto {
private double saldo;
public void einzahlen(double betrag) { // Methode verändert den Zustand
saldo += betrag;
}
}
Erzeugt und initialisiert ein Objekt
new aufgerufenpublic class Person {
private String name;
private int alter;
public Person(String name, int alter) { // Konstruktor
this.name = name;
this.alter = alter;
}
}
Person p = new Person("Anna", 30);
thisVerweis auf das eigene Objekt
this(...): Aufruf eines anderen Konstruktors derselben Klasseselfpublic class Punkt {
private int x, y;
public Punkt(int x, int y) {
this.x = x; // this.x = Attribut, x = Parameter
this.y = y;
}
public Punkt() {
this(0, 0); // ruft den anderen Konstruktor auf
}
}
Wer darf worauf zugreifen
| Modifizierer | Klasse selbst | Paket | Unterklasse | Überall |
|---|---|---|---|---|
public |
✔ | ✔ | ✔ | ✔ |
protected |
✔ | ✔ | ✔ | ✘ |
| (kein Modifizierer, „package-private“) | ✔ | ✔ | ✘ | ✘ |
private |
✔ | ✘ | ✘ | ✘ |
public class Beispiel {
public int a; // überall sichtbar
protected int b; // Paket + Unterklassen
int c; // nur im selben Paket
private int d; // nur in dieser Klasse
}
Kontrollierter Zugriff auf Attribute
private-Attributenprivate-Attributen, inkl. Prüfung möglichpublic class Person {
private int alter;
public int getAlter() { // Getter
return alter;
}
public void setAlter(int alter) { // Setter mit Prüfung
if (alter >= 0) {
this.alter = alter;
}
}
}
static (Klassen- vs. Instanzmember)Gehört zur Klasse statt zum Objekt
thispublic class Zaehler {
private static int anzahlObjekte = 0; // gemeinsam für alle
private int id; // pro Objekt
public Zaehler() {
anzahlObjekte++;
id = anzahlObjekte;
}
public static int getAnzahl() {
return anzahlObjekte;
}
}
new Zaehler();
new Zaehler();
System.out.println(Zaehler.getAnzahl()); // 2
Methode, die ohne Objekt aufrufbar ist
static, gehört zur Klasse, nicht zum Objektthis → kein direkter Zugriff auf Instanzattribute/-methodenstatic-MemberMath.max(), Integer.parseInt()), mainpublic class MatheHelfer {
public static int quadrat(int zahl) { // statische Methode
return zahl * zahl;
}
}
int q = MatheHelfer.quadrat(4); // 16, kein Objekt nötig
int m = Math.max(3, 7); // 7, statische Methode aus der Java-Bibliothek
public class Person {
private String name; // Instanzattribut
public static void test() {
// System.out.println(name); → Fehler: kein Objekt, also kein name
// this.name = "Anna"; → Fehler: kein this in static
}
}
| Instanzmethode | Statische Methode | |
|---|---|---|
| Gehört zu | einem Objekt | der Klasse |
| Aufruf | objekt.methode() |
Klasse.methode() |
| Objekt nötig | ja | nein |
Zugriff auf this / Instanzattribute |
ja | nein |
Interne Daten verstecken
privatepublic class Konto {
private double saldo; // von außen nicht direkt änderbar
public void abheben(double betrag) {
if (betrag > 0 && betrag <= saldo) {
saldo -= betrag;
}
}
public double getSaldo() {
return saldo;
}
}
Eigenschaften einer Oberklasse übernehmen
extends, nur eine Oberklassepublic class Tier {
protected String name;
public void essen() {
System.out.println(name + " isst.");
}
}
public class Hund extends Tier {
public void bellen() {
System.out.println(name + " bellt.");
}
}
Hund h = new Hund();
h.essen(); // geerbt
h.bellen(); // eigene Methode
Gleicher Aufruf, unterschiedliches Verhalten
Tier[] tiere = { new Hund(), new Katze() };
for (Tier t : tiere) {
t.lautGeben(); // Hund → "Wuff", Katze → "Miau"
}
superVerweis auf die Oberklasse
super(...): Konstruktor der Oberklasse, muss erste Anweisung seinsuper.methode(): Version der Oberklasse aufrufenpublic class Hund extends Tier {
private String rasse;
public Hund(String name, String rasse) {
super(name); // Konstruktor von Tier
this.rasse = rasse;
}
@Override
public void essen() {
super.essen(); // Verhalten der Oberklasse
System.out.println("...und wedelt mit dem Schwanz.");
}
}
Geerbte Methode neu umsetzen
@Override: Prüfung durch den Compilerpublic class Tier {
public void lautGeben() {
System.out.println("...");
}
}
public class Katze extends Tier {
@Override
public void lautGeben() {
System.out.println("Miau");
}
}
Unvollständige Basisklasse ohne eigene Objekte
abstractpublic abstract class Form {
public abstract double flaeche(); // muss implementiert werden
public void beschreibe() { // normale Methode
System.out.println("Fläche: " + flaeche());
}
}
public class Kreis extends Form {
private double radius;
public Kreis(double radius) { this.radius = radius; }
@Override
public double flaeche() {
return Math.PI * radius * radius;
}
}
// Form f = new Form(); → Fehler, abstrakt
Form f = new Kreis(2); // ok
Vertrag über Methoden
implementsdefault-Methoden mit Implementierungpublic interface Fahrbar {
void fahren();
}
public interface Tankbar {
void tanken(double liter);
}
public class Auto implements Fahrbar, Tankbar {
@Override
public void fahren() { System.out.println("Brumm"); }
@Override
public void tanken(double liter) { System.out.println(liter + " l getankt"); }
}
| Abstrakte Klasse | Interface | |
|---|---|---|
| Schlüsselwort | extends |
implements |
| Anzahl pro Klasse | nur eine | beliebig viele |
| Attribute | ja | nur Konstanten |
| Konstruktor | ja | nein |
| Zweck | gemeinsame Basis („ist ein“) | Fähigkeit / Vertrag („kann“) |
Teil-Ganzes-Beziehungen zwischen Objekten
Aggregation
Komposition
Multiplizität
| Notation | Bedeutung |
|---|---|
1 |
genau eins |
0..1 |
keins oder eins |
* bzw. 0..* |
beliebig viele (auch keins) |
1..* |
mindestens eins |
n..m |
zwischen n und m (z. B. 2..5) |
Team ◇────────── Spieler Team hat 0..* Spieler, Spieler in 0..* Teams
0..* 0..*
Haus ◆────────── Raum Haus hat 1..* Räume, Raum gehört zu genau 1 Haus
1 1..*
// Aggregation: Spieler existieren unabhängig vom Team
public class Team {
private List<Spieler> spieler = new ArrayList<>(); // 0..*
public void aufnehmen(Spieler s) { // Teil kommt von außen
spieler.add(s);
}
}
// Komposition: Räume existieren nur mit dem Haus
public class Haus {
private List<Raum> raeume = new ArrayList<>(); // 1..*
public Haus(int anzahlRaeume) {
for (int i = 0; i < anzahlRaeume; i++) {
raeume.add(new Raum()); // Haus erzeugt seine Teile selbst
}
}
}
| Aggregation | Komposition | |
|---|---|---|
| Bindung | lose | streng |
| Lebensdauer der Teile | unabhängig | an das Ganze gebunden |
| Teil in mehreren Ganzen | möglich | nein |
| UML-Symbol | ◇ leere Raute | ◆ gefüllte Raute |
| Multiplizität am Ganzen | beliebig (z. B. 0..*) |
1 bzw. 0..1 |
„Hat ein“ oder „ist ein“ – welche Beziehung passt?
extends// Vererbung: is-a
public class Hund extends Tier { }
// Komposition: has-a
public class Motor {
public void starten() { System.out.println("Motor läuft"); }
}
public class Auto {
private Motor motor = new Motor(); // Auto HAT einen Motor
public void starten() {
motor.starten(); // Aufgabe wird delegiert
}
}
Entwurfsmuster (Design Patterns): bewährte Lösungsvorlagen für wiederkehrende Designprobleme
Genau eine Instanz einer Klasse
private-Konstruktor + static-Methode liefert immer dieselbe Instanzpublic class Konfiguration {
private static Konfiguration instanz;
private Konfiguration() { } // von außen kein new möglich
public static Konfiguration getInstanz() {
if (instanz == null) {
instanz = new Konfiguration();
}
return instanz;
}
}
Konfiguration k1 = Konfiguration.getInstanz();
Konfiguration k2 = Konfiguration.getInstanz();
// k1 == k2 → true
Hinweis: einfache Variante nicht thread-sicher → Alternative:
enum-Singleton
Objekterzeugung zentral auslagern
public interface Form {
double flaeche();
}
public class FormFactory {
public static Form erzeuge(String typ, double wert) {
if (typ.equals("kreis")) {
return new Kreis(wert);
} else if (typ.equals("quadrat")) {
return new Quadrat(wert);
} else {
throw new IllegalArgumentException("Unbekannt: " + typ);
}
}
}
Form f = FormFactory.erzeuge("kreis", 2.0);
Automatisch über Änderungen informieren
public interface Beobachter {
void aktualisieren(String nachricht);
}
public class Newsletter { // Subject
private List<Beobachter> abonnenten = new ArrayList<>();
public void abonnieren(Beobachter b) {
abonnenten.add(b);
}
public void veroeffentlichen(String nachricht) {
for (Beobachter b : abonnenten) {
b.aktualisieren(nachricht);
}
}
}
public class Leser implements Beobachter {
private String name;
public Leser(String name) { this.name = name; }
@Override
public void aktualisieren(String nachricht) {
System.out.println(name + " erhält: " + nachricht);
}
}
Newsletter n = new Newsletter();
n.abonnieren(new Leser("Anna"));
n.abonnieren(new Leser("Ben"));
n.veroeffentlichen("Neue Ausgabe!");
// Anna erhält: Neue Ausgabe!
// Ben erhält: Neue Ausgabe!