IV: Objektorientierte Programmierung

Werbung
Universität Dortmund
IV: Objektorientierte
Programmierung
Java-Tutorium
August 2005
Folie 1 von 69
Universität Dortmund
Objekte
●
●
Klassen sind selbstdefinierte Typen, die
mehrere Variablen (Attribute)
zusammenfassen können.
Jede Klasse steht in einer eigenen Datei
<Klassenname>.java.
public class Geld{
public String waehrung;
public long betrag;
}
Java-Tutorium
August 2005
Folie 2 von 69
Universität Dortmund
Objekte
●
Ein Objekt ist eine Instanz einer Klasse.
●
Ein Objekt wird mit new erzeugt.
●
Auf die Attribute des Objekts wird mit .
zugegriffen.
Geld wenig;
wenig=new Geld();
wenig.waehrung="Pesos";
wenig.betrag=50;
System.out.println(wenig.betrag);
Java-Tutorium
August 2005
Folie 3 von 69
Universität Dortmund
Objekte
●
●
●
Es kann beliebig viele Objekte einer Klasse
geben.
Objekte werden von Java auf dem Heap
gespeichert.
In der Variablen ist nicht das Objekt, sondern
nur seine Adresse (ein Zeiger) gespeichert.
Java-Tutorium
August 2005
Folie 4 von 69
Universität Dortmund
Objekte
Geld wenig;
wenig=new Geld();
wenig.währung="Pesos";
wenig.betrag=40;
Geld viel=new Geld();
viel.währung="Franken";
viel.betrag=50000;
Heap
Geld
währung: Pesos
betrag: 40
Geld-Adresse wenig: 231231
Geld-Adresse viel:
Java-Tutorium
803541
August 2005
Geld
währung: Franken
betrag: 50000
Folie 5 von 69
Universität Dortmund
Aufgabe
●
●
●
Schreibe eine Klasse Punkt, die einen
zweidimensionalen Vektor speichert.
Schreibe eine Methode, die den Abstand
zwischen zwei Punkten berechnet.
Gib den Abstand zwischen (0,5.5) und (4,9)
aus.
Java-Tutorium
August 2005
Folie 6 von 69
Universität Dortmund
Zeiger
●
Objekte werden bei einer Zuweisung nicht
kopiert.
●
Stattdessen wird nur die Adresse kopiert.
●
gilt auch für Parameterübergabe
Java-Tutorium
August 2005
Folie 7 von 69
Universität Dortmund
Zeiger
Geld eines=new Geld();
eines.betrag=50;
Geld dasselbe;
dasselbe=eines;
System.out.println(dasselbe.betrag);
eines.betrag=3;
System.out.println(dasselbe.betrag);
Heap
Geld-Adr. eines:
467890
Geld-Adr. dasselbe: 467890
Java-Tutorium
August 2005
Geld
währung:
betrag: 3
Folie 8 von 69
Universität Dortmund
Zeiger
●
zum Vergleich nochmal mit int
int eines;
eines=50;
int dasgleiche=eines;
System.out.println(dasgleiche);
eines=3;
System.out.println(dasgleiche);
50
50
Java-Tutorium
August 2005
Folie 9 von 69
Universität Dortmund
Zeiger
●
●
●
Strings und Arrays sind ebenfalls Objekte.
Nur die Adresse ist in der Variablen
gespeichert.
Wir hatten große Mühe, Beispiele zu finden,
bei denen das nicht so sehr auffällt.
Java-Tutorium
August 2005
Folie 10 von 69
Universität Dortmund
Zeiger
●
was bei den Vergleichen mit == passiert ist
int[] a1=new int[2];
int[] a2=new int[2];
if(a1==a2){
...
}
int[]-Adr. a1: 4401455
int[]-Adr. a2: 9456431
Java-Tutorium
August 2005
Heap
int[]
0: 0
1: 0
int[]
0: 0
1: 0
Folie 11 von 69
Universität Dortmund
Zeiger
●
●
Bei der Erzeugung mit new werden die
Variablen in Objekten automatisch
initialisiert.
Die Defaultwerte entsprechen denen von
Arrayelementen.
Punkt p=new Punkt();
System.out.println(p.x);
0.0
Java-Tutorium
August 2005
Folie 12 von 69
Universität Dortmund
Aufgabe
●
●
●
●
Schreibe eine Methode, die zwei Punkte
koordinatenweise vergleicht.
Schreibe eine Methode, die einen Punkt
kopiert.
Erstelle einen Punkt, setze die Koordinaten
auf (3,4) und kopiere den Punkt.
Vergleiche das Original mit der Kopie —
einmal mit == und einmal mit deiner
Methode.
Java-Tutorium
August 2005
Folie 13 von 69
Universität Dortmund
Zeiger
●
Garbage Collection (Müllabfuhr)
Punkt p=new Punkt();
p=new Punkt();
p=new Punkt();
System.gc();
Heap
Punkt
x: 0
y: 0
Punkt
x: 0
y: 0
Punkt p: 789045601
Punkt
x: 0
y: 0
Java-Tutorium
August 2005
Folie 14 von 69
Universität Dortmund
Zeiger
●
Garbage Collection (Müllabfuhr)
Punkt p=new Punkt();
p=new Punkt();
p=new Punkt();
System.gc();
Heap
Punkt p: 789045601
Punkt
x: 0
y: 0
Java-Tutorium
August 2005
Folie 15 von 69
Universität Dortmund
Zeiger
●
●
Die Garbage Collection ist ein besonderes
Feature von Java.
Sie muss normalerweise nicht explizit
aufgerufen werden.
Java-Tutorium
August 2005
Folie 16 von 69
Universität Dortmund
Zeiger
●
Zeiger, die nirgendwohin zeigen
Punkt p=new Punkt();
p=null;
System.gc();
Heap
Punkt p: 0000000000000
Java-Tutorium
August 2005
Folie 17 von 69
Universität Dortmund
Zeiger
●
●
NullPointerException
alias allgemeine Schutzverletzung, alias
Segmentation Violation
Punkt punkt=null;
System.out.println(punkt.x);
java.lang.NullPointerException
at Main.main(Main.java:119)
Exception in thread "main"
Java-Tutorium
August 2005
Folie 18 von 69
Universität Dortmund
Zeiger
●
●
Objekte können selbst wieder Zeiger
enthalten.
Der Defaultwert von allen Zeigern ist null.
public class Strecke{
public Punkt start;
public Punkt ende;
}
Java-Tutorium
August 2005
Folie 19 von 69
Universität Dortmund
Zeiger
●
Verzeigerung
Punkt p1=new Punkt();
Punkt p2=new Punkt();
Strecke s=new Strecke();
s.start=p1;
s.ende=p2;
p1=null;
p2=null;
System.gc();
Punkt p1:
00000000
Punkt p2:
00000000
Strecke s : 87301564
Java-Tutorium
August 2005
Heap
Punkt
x: 0
y: 0
Punkt
x: 0
y: 0
Strecke
start: 12896453
ende : 43678941
Folie 20 von 69
Universität Dortmund
Aufgabe
●
●
●
Schreibe eine Klasse Kreis, die aus einem
Mittelpunkt und einem Radius besteht.
Schreibe eine Methode, die bestimmen kann,
ob ein Punkt innerhalb des Kreises liegt.
Liegt (1.7,2.6) in einem Kreis mit Radius 1
um (1,2)?
Java-Tutorium
August 2005
Folie 21 von 69
Universität Dortmund
Aufgabe
●
●
●
Schreibe eine Klasse Ring mit den Methoden
–
String weiter(Ring)
–
void fügeHinzu(Ring, String)
Die Methode weiter gibt der Reihe nach
jeweils einen String aus dem Ring aus.
fügeHinzu fügt den String in den Ring an der
Stelle ein, die als nächstes dran ist.
Java-Tutorium
August 2005
Folie 22 von 69
Universität Dortmund
Tipp
●
Verwende folgende Struktur.
Heap
Ring
aktuell:
RingElement
vor:
zurück:
RingElement
vor:
zurück:
RingElement
vor:
zurück:
Java-Tutorium
August 2005
RingElement
vor:
zurück:
Folie 23 von 69
Universität Dortmund
Objekte
●
Methoden in anderen Klassen
●
zusammen, was zusammen gehört
public class Punkt{
public double x;
public double y;
}
public static double abstand(Punkt a,
Punkt b){
double x=a.x-b.x;
double y=a.y-b.y;
return Math.sqrt(x*x+y*y);
}
Java-Tutorium
August 2005
Folie 24 von 69
Universität Dortmund
Objekte
●
Methoden in anderen Klassen aufrufen
public static void main(String[] arguments){
Punkt p1=new Punkt();
Punkt p2=new Punkt();
p2.x=3;
p2.y=4;
System.out.println(Punkt.abstand(p1, p2));
}
5.0
Java-Tutorium
August 2005
Folie 25 von 69
Universität Dortmund
Objekte
●
Viele Methoden arbeiten mit einem Objekt.
public class Punkt{
...
}
public static double abstandZuNullA(Punkt p){
double xQuadrat=p.x*p.x;
double yQuadrat=p.y*p.y;
return Math.sqrt(xQuadrat+yQuadrat);
}
Java-Tutorium
August 2005
Folie 26 von 69
Universität Dortmund
Objekte
●
Methoden non-static definieren
public class Punkt{
...
}
public double abstandZuNullB(){
double xQuadrat=this.x*this.x;
double yQuadrat=this.y*this.y;
return Math.sqrt(xQuadrat+yQuadrat);
}
Java-Tutorium
August 2005
Folie 27 von 69
Universität Dortmund
Objekte
●
nochmal zum Vergleich
public class Punkt{
...
}
public static double abstandZuNull(Punkt p){
double xQuadrat=this/p.x*this/p.x;
double yQuadrat=this/p.y*this/p.y;
return Math.sqrt(xQuadrat+yQuadrat);
}
Java-Tutorium
August 2005
Folie 28 von 69
Universität Dortmund
Objekte
●
Wie bestimmt man jetzt, welchen Punkt man
meint?
Punkt p1=new Punkt();
Punkt p2=new Punkt();
p2.x=4;
System.out.println(p1.abstandZuNullB());
System.out.println(p2.abstandZuNullB());
0.0
4.0
Java-Tutorium
August 2005
Folie 29 von 69
Universität Dortmund
Objekte
//in Main.java
public static void main(...){
Punkt p=new Punkt();
double z=p.abstandZuNullB();
}
//in Punkt.java
public double abstandZuNullB(){
double xQdr=this.x*this.x;
double yQdr=this.y*this.y;
return Math.sqrt(xQdr+yQdr);
}
Punkt p:
32383409
this:
<static>
Heap
Punkt
x: 0
y: 0
double z: 0
Java-Tutorium
August 2005
Folie 30 von 69
Universität Dortmund
Objekte
●
Andere Parameter darf man natürlich
trotzdem noch haben.
public class Punkt{
...
}
public double abstandZu(Punkt andererPunkt){
double dx=this.x-andererPunkt.x;
double dy=this.y-andererPunkt.y;
return Math.sqrt(dx*dx+dy*dy);
}
Java-Tutorium
August 2005
Folie 31 von 69
Universität Dortmund
Aufgabe
●
●
Schreibe eine Methode, die auf einem Kreis
aufgerufen wird und seine Fläche zurückgibt.
Schreibe eine Methode schließeEin(Punkt),
die einen Kreis falls nötig vergrößert, so dass
er den angegebenen Punkt einschließt.
Java-Tutorium
August 2005
Folie 32 von 69
Universität Dortmund
Objekte
●
Es gibt selbstverständlich weiterhin
verschachtelte Methodenaufrufe.
public class Buch{
public Cover cover;
public Seite[] seiten;
}
public double dicke(){
double ergebnis=this.cover.dicke();
for(int i=0;i<this.seiten.length;i++){
ergebnis+=this.seiten[i].papierDicke();
}
return ergebnis;
}
Java-Tutorium
August 2005
Folie 33 von 69
Universität Dortmund
Objekte
●
Methoden auf das aktuelle Objekt kann man
(logisch!) mit this aufrufen.
public class Brief{
public Adresse wohin;
public String text;
}
public void druckeAdresse(){
this.wohin.drucke();
}
public void drucke(){
this.druckeAdresse();
System.out.println(this.text);
}
Java-Tutorium
August 2005
Folie 34 von 69
Universität Dortmund
Aufgabe
●
●
●
●
Baue die alten Methoden fügeEin und weiter
in die Klasse Ring ein.
Schreibe eine Methode int anzahl().
Schreibe eine Methode boolean enthält
(String) (die aktuelle Position soll nicht
verändert werden).
Schreibe eine Methode fügeAlleEin(Ring).
–
Tipp: Benutze die anderen Methoden
dafür.
Java-Tutorium
August 2005
Folie 35 von 69
Universität Dortmund
Objekte
●
Auf private Attribute und Methoden kann
nur aus der Klasse zugegriffen werden, in der
sie definiert sind.
●
ermöglicht Kapselung
●
verhindert unerwünschte Seiteneffekte
Java-Tutorium
August 2005
Folie 36 von 69
Universität Dortmund
Objekte
●
wenn man es trotzdem versucht
public class Punkt{
private double x;
private double y;
}
public class Main{
public static void main(String[] s){
Punkt p=new Punkt();
System.out.println(p.x);
}
}
Main.java [37:1] x has private access in Punkt
System.out.println(p.x);
1 error
^
Java-Tutorium
August 2005
Folie 37 von 69
Universität Dortmund
Objekte
●
Wie kommt man jetzt an die Werte?
●
get-Methoden
public class Punkt{
private double x;
private double y;
}
public double getX(){
return this.x;
}
public double getY(){
return this.y;
}
Java-Tutorium
August 2005
Folie 38 von 69
Universität Dortmund
Objekte
●
set-Methoden
public class Geld{
private long betrag;
}
public void setBetrag(long eur, int ct){
this.betrag=euro*100+cent;
}
public long getEuros(){
return this.betrag/100;
}
public int getCent(){
return this.betrag%100;
}
Java-Tutorium
August 2005
Folie 39 von 69
Universität Dortmund
Objekte
●
Konstruktoren
public class Punkt{
private double x;
private double y;
}
public Punkt(double x, double y){
this.x=x;
this.y=y;
}
...
Java-Tutorium
August 2005
Folie 40 von 69
Universität Dortmund
Objekte
●
Konstruktoren benutzen
Punkt p1=new Punkt(1, 1);
Punkt p2=new Punkt(2, 2);
System.out.println(Punkt.abstand(p1, p2));
1.4142135623730951
Java-Tutorium
August 2005
Folie 41 von 69
Universität Dortmund
Objekte
●
Der Standardkonstruktor verschwindet.
Punkt p1=new Punkt(1, 1);
Punkt p2=new Punkt();
System.out.println(Punkt.abstand(p1, p2));
Main.java [34:1] cannot resolve symbol
symbol : constructor Punkt ()
location: class Punkt
Punkt p2=new Punkt();
^
1 error
Java-Tutorium
August 2005
Folie 42 von 69
Universität Dortmund
Objekte
●
den Standardkonstruktor wiederbekommen
public class Punkt{
private double x;
private double y;
public Punkt(){
}
}
public Punkt(double x, double y){
this.x=x;
this.y=y;
}
...
Java-Tutorium
August 2005
Folie 43 von 69
Universität Dortmund
Aufgabe
●
●
●
Schreibe eine Klasse Konto mit einem
Attribut guthaben.
Die Klasse soll einzahlen, abheben und
Kontostand anzeigen unterstützen.
Ein Konto muss immer mit einer Einzahlung
eröffnet werden.
Java-Tutorium
August 2005
Folie 44 von 69
Universität Dortmund
Objekte
●
abkürzende Schreibweise ohne this
public class Konto{
private long guthaben;
}
public Konto(long einzahlung){
zahleEin(einzahlung);
}
public void zahleEin(long betrag){
guthaben+=betrag;
}
Java-Tutorium
August 2005
Folie 45 von 69
Universität Dortmund
Objekte
●
Manchmal braucht man this trotzdem.
public class Person{
public void heirate(Person partner){
Standesamt.heiraten(this, partner);
}
}
Java-Tutorium
August 2005
Folie 46 von 69
Universität Dortmund
Exceptions
●
private reicht nicht immer zum Schutz.
●
Fehler niemals stillschweigend ignorieren!
public void hebeAb(int betrag){
if(guthaben>=betrag){
guthaben-=betrag;
}
}
public static void überweise(Konto von, Konto
nach, int betrag){
}
von.hebeAb(betrag);
nach.zahleEin(betrag);
Java-Tutorium
August 2005
Folie 47 von 69
Universität Dortmund
Exceptions
●
eine Exception werfen
public void hebeAb(int betrag){
//testen
if(betrag<=0)throw new RuntimeException();
if(guth<betrag)throw new RuntimeException();
}
//ausführen
guth-=betrag;
Java-Tutorium
August 2005
Folie 48 von 69
Universität Dortmund
Exceptions
●
eine Exception "geworfen bekommen"
public static void main(String[] arguments){
Konto pleite=new Konto(50);
pleite.hebeAb(35);
System.out.println(pleite.getKontostand());
pleite.hebeAb(23);
System.out.println(pleite.getKontostand());
}
15
java.lang.RuntimeException:
at Konto.hebeAb(Konto.java:14)
at Main.main(Main.java:36)
Exception in thread "main"
Java-Tutorium
August 2005
Folie 49 von 69
Universität Dortmund
Exceptions
●
eine Exception fangen
Konto pleite=new Konto(50);
try{
pleite.hebeAb(35);
pleite.hebeAb(23);
System.out.println("Juhuu");
}catch (RuntimeException exc){
System.out.println("Mist");
}
System.out.println(pleite.getKontostand());
Mist
15
Java-Tutorium
August 2005
Folie 50 von 69
Universität Dortmund
Exceptions
●
Es kann natürlich auch mal gut gehen.
Konto pleite=new Konto(100);
try{
pleite.hebeAb(35);
pleite.hebeAb(23);
System.out.println("Juhuu");
}catch (RuntimeException exc){
System.out.println("Mist");
}
System.out.println(pleite.getKontostand());
Juhuu
42
Java-Tutorium
August 2005
Folie 51 von 69
Universität Dortmund
Exceptions
●
●
●
●
Sobald eine Exception geworfen wird, sucht
java das letzte (innerste) try, das bei der
Ausführung passiert wurde.
Dann springt java zu dem catch-Block, der
zu diesem try gehört.
Gibt es kein try, wird eine Nachricht
ausgegeben und das Programm beendet.
Warnung! Lügen für Kinder!
Java-Tutorium
August 2005
Folie 52 von 69
Universität Dortmund
Aufgabe
●
●
Füge der Klasse Konto eine pin hinzu, die bei
jeder kritischen Operation als Paramter
korrekt angegeben werden muss.
Sichere die Klasse Konto mit Exceptions ab.
Java-Tutorium
August 2005
Folie 53 von 69
Universität Dortmund
Exceptions
●
Was soll man hier als Fehlermeldung
ausgeben?
int geld=readInt("Wieviel wollen Sie abheben?");
String pin=readString("Ihre Geheimzahl");
try{
konto.hebeAb(geld, pin);
}catch (RuntimeException exc){
System.out.println("Falsche PIN?");
System.out.println("Kein Geld mehr?");
}
Java-Tutorium
August 2005
Folie 54 von 69
Universität Dortmund
Exceptions
●
eine neue Klasse von Exceptions deklarieren
public class KontoÜberzogenException
extends RuntimeException{
}
Java-Tutorium
August 2005
Folie 55 von 69
Universität Dortmund
Exceptions
●
die richtige Exception werfen
public void hebeAb(long betrag, String pin){
if(!pin.equals(this.pin)){
throw new FalschePinException();
}
if(betrag<0){
throw new NegativerBetragException();
}
if(guth<betrag){
throw new KontoÜberzogenException();
}
}
guthaben-=betrag;
Java-Tutorium
August 2005
Folie 56 von 69
Universität Dortmund
Exceptions
●
selektiv Exceptions fangen
int geld=readInt("Wieviel wollen sie abheben");
String pin=readString("Ihre Geheimzahl");
try{
konto.hebeAb(geld, pin);
}catch (FalschePinException exc){
System.out.println("Falsche PIN");
}catch (KontoÜberzogenException exc)
System.out.println("Sie sind pleite");
}catch (NegativerBetragException exc){
System.out.println("Trottel!");
}
Java-Tutorium
August 2005
Folie 57 von 69
Universität Dortmund
Exceptions
●
catch (RuntimeException exc) fängt auch
eine KontoÜberzogenException
●
Reihenfolge beachten
int geld=readInt("Wieviel wollen sie abheben");
String pin=readString("Ihre Geheimzahl");
try{
konto.hebeAb(geld, pin);
}catch (FalschePinException exc){
System.out.println("Falsche PIN");
}catch (RuntimeException exc){
System.out.println("Anderer Fehler");
}
Java-Tutorium
August 2005
Folie 58 von 69
Universität Dortmund
Exceptions
●
Fehlermeldung von der Exception bekommen
try{
throw new RuntimeException("Hallo");
}catch (RuntimeException exc){
String nachricht=exc.getMessage();
System.out.println(nachricht);
}
Hallo
Java-Tutorium
August 2005
Folie 59 von 69
Universität Dortmund
Exceptions
●
Call-Stack ausgeben
–
hilft dem Programmierer, die Ursache zu
verstehen
try{
throw new RuntimeException("Hallo");
}catch (RuntimeException exc){
exc.printStackTrace();
}
java.lang.RuntimeException: Hallo
at Huibu.wirfMal(Huibu.java:12)
at Konto.hebeAb(Konto.java:14)
at Main.main(Main.java:36)
Java-Tutorium
August 2005
Folie 60 von 69
Universität Dortmund
Exceptions
●
Es gibt neben RuntimeExceptions auch noch
normale (checked) Exceptions.
public class PleiteExc extends Exception{
}
Java-Tutorium
August 2005
Folie 61 von 69
Universität Dortmund
Exceptions
●
Checked Exceptions müssen deklariert oder
gefangen werden.
public void hebAb(int betrag){
if(betrag<=0)throw new NegativerBetragExc();
if(guthaben<betrag)throw new PleiteExc();
}
guthaben-=betrag;
Konto.java [12:1] unreported exception
java.lang.Exception; must be caught or declared
to be thrown
if(guthaben<betrag) throw new PleiteExc();
1 error
^
Java-Tutorium
August 2005
Folie 62 von 69
Universität Dortmund
Exceptions
●
Checked Exceptions müssen deklariert oder
gefangen werden.
public void hebAb(int betrag) throws PleiteExc{
if(betrag<=0) throw new NegativerBetragExc();
if(guthaben<betrag) throw new PleiteExc();
}
guthaben-=betrag;
Java-Tutorium
August 2005
Folie 63 von 69
Universität Dortmund
Exceptions
●
Auch wer eine Methode mit throws aufruft,
muss die Exception fangen oder deklarieren.
public static void main(String[] arguments)
throws PleiteExc{
Konto konto=new Konto(50);
konto.hebeAb(35);
System.out.println(konto.getKontostand());
konto.hebeAb(23);
System.out.println(konto.getKontostand());
}
Java-Tutorium
August 2005
Folie 64 von 69
Universität Dortmund
Exceptions
●
RuntimeExceptions werfen, wenn die
aufrufende Methode etwas unsinniges will
–
IllegalArgumentException
–
ArrayIndexOutOfBoundsException
–
NullPointerException
–
NegativerBetragException
Java-Tutorium
August 2005
Folie 65 von 69
Universität Dortmund
Exceptions
●
checked Exceptions werfen, wenn ein an sich
vernünftiger Aufruf nicht ausgeführt werden
kann
–
FileNotFoundException
–
MidiUnavailableException
–
NoRouteToHostException
–
KontoÜberzogenException
Java-Tutorium
August 2005
Folie 66 von 69
Universität Dortmund
Exceptions
●
●
●
In der Methode wird die Ausnahme nur
entdeckt.
Die Ausnahmebehandlung wird der
aufrufenden Methode überlassen.
throws sagt der aufrufenden Methode, was
prinzipiell schief gehen könnte.
Java-Tutorium
August 2005
Folie 67 von 69
Universität Dortmund
Exceptions
●
Die aufrufende Methode hat mehr
Kontextinformation
–
Eine Klasse Geldautomat bietet dem
Benutzer an, weniger abzuheben
–
Eine Überweisungsmethode reicht die
Exception einfach nach oben durch
Java-Tutorium
August 2005
Folie 68 von 69
Universität Dortmund
Aufgabe
●
●
●
Schreibe eine Klasse Geldautomat, die ein
User Interface im Textmodus für die drei
Funktionen bietet.
Die Aufgabe lässt viel Spielraum:
–
Muss man das Abheben bestätigen?
–
Muss man die PIN nochmal eingeben,
wenn man sich beim Betrag vertippt?
–
Kann man zwischendurch abbrechen?
KISS: Keep It Simple and Stupid
Java-Tutorium
August 2005
Folie 69 von 69
Herunterladen