Variabelzugriff auf fremde Packages

Status
Nicht offen für weitere Antworten.

michi2

Bekanntes Mitglied
Hallo,
In verschiedenen Threats hir habt ihr mir empfohlen meine Dateien in verschiedene Packages zu verteilen, also nicht mehr alle in Ordner/Packet x/ sondern in den Ordner/Packeten x/a/, x/b/, x/c/...
Nun wollte ich dies bei mir tun, aber:
Um von einer Classe in x/a/... auf eine Variable in x/Classe.java zuzugreifen muss diese als public deffiniert sein, jedoch habt ihr mir auch in zahlreiche Threats empfohlen nicht alle Variablen mehr oder wahllos als public zu deklarieren!

Wie soll ich das machen?

Vielen Dank schon mahl im voraus,
Michi
 
Hi,
warum musst du denn direkt auf eine Variable zugreifen? Ist hier wirklich eine ernst gemeinte Frage.
Eine Klasse sollte immer eine gewissen zusammen gehörige Funktionalität kapseln. Dass heißt wenn du eine Klasse X hast, dann bietet diese die Methoden a, b und c an. Die machen alle etwas ganz bestimmtes. Dazu greifen die vielleicht auf andere Klassen und garantiert auf private Variablen zu. Ein direkter Zugriff auf Variablen ist also nie nötig.
Gut sehen kannst du es, wenn du Interfaces verwendest. Diese sind sehr abstrakt, hier stehen nur die öffentlichen (also von aussen sichtbaren) Methoden mit Rückgabewert und Parameter drin. Das reicht aus (ist sogar zu empfehlen) um auf dieser Basis sehr komplexe Programme zu erstellen. Du modellierst dein eigentliches Programm so abstrakt wie möglich (also z.B. mit Interfaces). Im Programm wird dann zwar mit konkreten Instanzen gearbeitet, da diese aber das entsprechende Interface implentieren wären all diese Instanzen einfach austauschbar. Die eigentliche Implementierung kann dir dort also egal sein. Der klare Vorteil ist, du musst gar nicht wissen wie die Variablen solcher Klassen aussehen.

Warum also willst du direkt auf Variablen zugreifen? Das einzigste wo so etwas sinnvoll ist, ist imho es bei konstanten zu tun, diese sind dann aber eben auch nicht variabel und hätten die Form:
Code:
public static final int EINE_BSP_KONSTANTE = 1;
public static final int EINE_ANDERE = 2;
 

michi2

Bekanntes Mitglied
Nun, ich wollte die ActionListener ausgliederen in ein Packet 'Listeners'. Und da muss ich nun mahl auf die Variablen des Programms zugreifen und diese verändern...
Ich verstehe allerdings ehrlich gesagt deine Lösung nicht ganz... Irgentwie scheine ich zu blöd zu sein um zu verstehen was es mit den Interface auf sich hat! :(
 

André Uhres

Top Contributor
Ein package x gibt es zwar in deinem Beispiel nicht (also auch keine Klasse "x/Classe.java"), aber dein Problem hat ja auch nichts mit packages zu tun, sondern einfach mit der Ausgliederung einer Klasse, das könnte ebensogut in demselben package geschehen. Um die Variablen einer anderen Klasse anzuzapfen kannst die sie im Konstruktor übergeben oder mit public get../set.. Methoden.
 

michi2

Bekanntes Mitglied
Hm... Um mich noch mahl genauer aus zu drücken:
ich hab ein Packet x
mit der Klasse y in der Datei y, welche die Main-Methode und ein ganze reihe von Variablen enthält.
Und eine Klasse z in der Datei z, welches ein Actionlistener ist.
Nun will ich die Datei z in ein extra Packet nammens 'Listeners' verschieben.
In z wird an vielen Stellen aut die Variablen von der Klasse y zugegriffen.
Eine Ubergebung der Dateien mitels Konstruktor geht also schonmahl nicht! Und wenn ich für jede Variable eine get und eine set methode deffiniere bläht das mein (ohnehin schon viel zu große) Klasse z extrem auf....
 
Da ist halt die Frage, ob man wirklich die ActionListener auslagern sollte. Ein Alternatives Design ist es doch, dass du nicht den Listener selbst auslagerst, sondern die Logik des Listeners (also was genau gemacht wird wenn das Ereignis auftritt).
Der Teil mit den Interfaces ist auch etwas weniger kompletter Anfänger. Aber es bietet sich halt dieses Design so früh wie möglich an und ist gar nicht weiter kompliziert. Was eine Klasse ist weißt du ja sicherlich schon. Ich weiß nicht wie es dann um dein Wissen um Vererbung aussieht? Oder abstrakte Klassen?
Ein Interface ist jedenfalls komplett abstrakt. Alles was da drin stehen darf sind Methoden. Die Sichtbarkeit ist dabei automatisch auf public festgelegt. Keine der Methoden wird aber in einem Interface implementiert, du gibst so zu sagen nur die Signatur bekannt.
Ein sehr einfaches Beispiel wäre ein Stack. Werde den mal als Stapel bezeichnen um evtl. Namensüberschneidungen zu vermeiden (einen Stack gibt ja in Java schon). Die Eigenschaften eines Stack sind sehr einfach, ich kann ein Element mit push auf den Stapel legen und mit pop das oberste zurück holen. Sagen wir ich möchte noch wissen wie voll der Stack ist.
Diese drei Dinge wären die volle Funktionalität eines Stack. Dazu muss ich aber nicht Wissen ob die Elemente in einem Array gespeichert werden oder in einer Liste, in einem Baum oder sonst wie.
Ein Interface würde hier wie folgt aussehen:
Code:
public interface IStapel<T> {
	
	void push(T t);
	
	T pop();
	
	int getCount();
}
IStapel ist jetzt so ein abstraktes Interface. Du weißt, dass alle IStapel (also "Nachfolger") diese öffentlichen Methoden haben. Ein solcher "Nachfolger" muss diese Schnittstelle implementieren. Wie du siehst steht im Interface noch kein Code, was z.B. push macht. Zwei mögliche Implementierungen könnten so aussehen:
Code:
class StapelArray<T> implements IStapel<T> {

	private T[] objects;
	
	private void vergroesserArray() {
		// irgendwas
	}
	
	private void verkleinererArray() {
		// irgendwas
	}
	
	public void push(T t) {
		// schlechte Implementierung, aber hier egal
	
		this.vergroesserArray();		
		this.objects[this.objects.length - 1] = t;
	}

	public T pop() {
		
		if (this.getCount() < 1) {
			return null;
		}
		
		T result = this.objects[this.objects.length - 1];
	    this.verkleinererArray();
		
		return result;
	}

	public int getCount() {
		return this.objects.length;
	}

}

class StapelVector<T> implements IStapel<T> {

	private Vector<T> vector = new Vector<T>();
	
	public void push(T t) {
		this.vector.add(t);
	}

	public T pop() {
		if (this.getCount() < 1) {
			return null;
		}
		
		T result = this.vector.lastElement();
		this.vector.remove(this.vector.lastElement());
		
		return result;
	}

	public int getCount() {
		return this.vector.size();
	}

}

Hier hättest du jetzt ein einfaches Beispiel für zwei sehr verschiedene Implementierungen. Bei dem einen wird für den Stapel ein Array verwendet. Dieses muss in der Größe angepasst werden, wenn du ein Element hinzufügst oder entfernst. Bei der anderen Implementierung wird ein Vector verwendet (der kümmert sich selbst um die Größe).
Für den Stapel ist das jedoch unwichtig. Du möchtest nur ein Element mit push oben rauf legen und mit pop entfernen, mit getCount() die Größe bekommen.
In deinem Programm kannst du jetzt mit Variablen vom Typ IStapel arbeiten. Was für eine Implementierung dahinter steckt ist dir egal
Code:
public void foo(final IStapel<Integer> stapel) {
  // tu irgenwas mit dem Stapel
  
  stapel.push(1);
  stapel.push(2);
  stapel.push(new Integer(10283));
  stapel.pop();
  ...
}

// eine Main zum Testen:
public static void main(String[] args) {
  
  IStapel<Integer> stapel1 = new StapelArray<Integer>();
  IStapel<Integer> stapel2 = new StapelVector<Integer>();

  foo(stapel1); 

  foo(stapel2);
}
Jetzt könntest du leicht die Implementierung des Stapels austauschen und foo würde immer funktionieren. Wie dein Stapel intern arbeitet interessiert dich einfach mal garnicht. Ok, beim Stapel gibt es sicherlich nur begrenzt viele sinnvolle Möglichkeiten. Aber Interfaces kannst du für jedes Programm verwenden. java.util.List<T> ist zum Beispiel ein sehr schönes Interface. Es kann von dir überall dort verwendet werden, wo du die Eigenschaften einer Liste benötigst. Ob die Implementierung die du verwendest dann mit einer verketteten Liste, einem dynamischen Array (etwas effizienter gemacht als hier) oder vielleicht mittels Hashes arbeitet kann dir egal sein. Das Interface sichert dir nur zu, dass du die Schnittstelle (die öffentlichen Methoden) kennst. Natürlich kann eine Klasse die ein Interface implementiert mehr öffentliche Methoden als die des Interface haben, aber eben nie weniger.
Ich hoffe der Vorteil ist grob klar (wahrscheinlich erklärt dir jedes Javabuch das deutlich besser als ich).

Mit dieser Abstraktion gewinnst du jedenfalls eine Menge. Du hast ein sehr Abstraktes Design, dass heißt die Wahl der Klassen die du einsetzt ist recht wenig eingeschränkt. Du kannst so in Anwendungen leicht neue bessere und perfomantere Klassen einsetzen und änderst nur an einer Stelle etwas (den Aufruf des Konstruktors). Die ganze Logik bleibt erhalten. Zudem siehst du hier, dass du dir um Variablen gar keine Kopf machen brauchst. Z.B. speichern beide Implemeniterungen Elemente in einer Datenstruktur, das sollen sie ja auch. Aber sie verwalten diese Datenstruktur (die zu ihnen gehört). Von aussen möchtest du dich darum gar nicht kümmern. Du schmeist einen Wert in die Schwarze Kiste IStapel und er landet auf einem Stapel. Du drückst auf der Kiste den Knopf pop und das oberste Element kommt raus (null wenn Stapel leer ist).
Ein weiterer Vorteil ist, dass du so Arbeit leicht verteilen kannst. Steht die Schnittstelle fest, kannst du schonmal diese als Variable in einer Klasse verwenden. Das es noch gar keine Implemtierung dieser Schnittstelle geben muss führt zu keinem Problem mit dem Compiler (die Schnittstelle sichert schließlich zu, dass jede verwendete Implentierung diese Methoden haben muss). So kannst du auch leicht eine Dummy-Implementierung für erste Tests schreiben während eine andere Gruppe eine effiziente Implementierung erstellt. Ist die irgendwann fertig, das Tauschen ist kein Problem!
Natürlich sind das nicht alle Vorteile, aber imho schon mal genügend um ein wenig Motivation für den Einsatz zu geben. Gerade in kleinen Projekten fehlt diese häufig. Wenn man mal nur was schreibt, gerade auch zu hause, dann denkt man häufig der Aufwand lohnt sich gar nicht. Aber wenn man sich das nicht angewöhnt, fällt es einem nur später umso schwerer. Gerade im Beruf wirst du schnell merken, wo du im Design geschlampt hast. Da denkt man dann schnell mal, dass die Zeit knapp wird und macht etwas an der ein oder anderen Stelle unsauber. Dann kommt man damit zwar über einen Meilenstein und der Kunde ist zufireden. Dann kommen jedoch die neuen Wünsche und Nachbesserungen und ruck-zuck kostet das alles unnötig viel Zeit (deutlich mehr als wenn man es gleich richtig gemacht hätte).

Ok, genug abgeschweift. Kommen wir mal zurück zur eigentlichen Frage.
Was genau muss gemacht werden? Es tritt ein Ereignis ein. Dein Listener weiß erstmal nicht genau wer oder was dieses Ereignis ausgelöst hat (ist dem einfach mal egal). Er weiß nur, Ereignis xyz eingetreten und ruft die entsprechende Methode auf. Nehmen wir hier (o.B.d.A.) einfach mal an, du hast einen Button. Für diesen registrierst du einen MouseListener der auf ein Click reagiert. Dazu überschreibst du einfach die Methode eine MouseAdapters:
Code:
public class DummyMouseListener extends MouseAdapter {

	public void mouseClicked(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON1) {
                           // Aufruf irgendeiner Klasse, die irgendwas berechnen soll
			new Foo().doFoo();
		}
	}
}
Ok, diesen Listener registrierst du jetzt beim entsprechenden Button (oder bei allen Elementen, die dieses Event aufrufen). Diese brauchen dazu nur diese Klasse kennen (kein Variable in ihr) und die Klassen selbst muss gar nicht wissen bei wem sie registriert wird.
Jetzt wird bei einem Click mit dem linken MouseButton die Methode doFoo() der Klasse Foo aufgerufen. Diese kann jetzt in Ruhe einen Wert berechnen. Dazu greift sie nur auf eigenen Methoden zurück. Irgendwann ist sie fertig und möchte nun das Ergebnis ausgeben. Da du eine GUI hast, bietet sich diese dafür natürlich an.
Jetzt ist also die Frage, wie zeigst du das Ergebnis in deiner GUI an. Sagen wir hier wieder der Einfachheit halber, du möchtest das Ergebnis auf einem JLabel ausgeben.
Jetzt hast du mind. zwei Möglichkeiten. doFoo() kümmert sich selbst drum. Es kennt das JLabel direkt (also die Variable) und ruft von dem aus die Methode setText auf. Das gleiche machen doFoo2 und doFoo3, die berechnen was anderes und geben es auf diesem Label aus.
Ok, ich hab jetzt ein schönes Beispiel an dem ich das weiter erklären möchte: Ein einfacher Taschenrechner. Wie der Funktioniert ist erstmal egal. Du hast die Button und ihre Listener schon fertig. Oben hast du ein JLabel (um bei dem zu bleiben), dass immer das aktuelle Ergebnis anzeigt. Statt den Foos gibt es jetzt die unterschiedlichen Berechnungen. Du hast eine Methode addiere, eine substrahiere und eine multipliziere. Aber natürlich geben die alle immer den Wert auf dem gleichen Label aus (halt oben die Zeile des Taschenrechners). Greifen die Methoden direkt auf dieses Label zu klappt das soweit auch ohne Probleme. Dazu müssen sie natürlich die Variable kennen, auch kein Problem, die eine wäre dann public. Aber was wenn du jetzt dein Design änderst? Du gibst das Ergebnis jetzt z.B. nicht mehr auf einem JLabel aus. Oder sagen wir du änderst jetzt die Farbe wenn der Wert negativ ist in rot, sonst schwarz. Dann hast du hier schon drei Stellen an denen die Prüfung ob positiv oder negativ rein muss. Und auch die Logik zum ändern muss hier rein. Natürlich hast du auch deutlich mehr Operationen als 3, dem entsprechend viele Stellen wo du es änderst. Sieht dann sicherlich auch gut aus, wenn du eine Stelle davon zu ändern vergisst...
Du siehst es ist viel schöner eine eigene Methode zu erstellen, die nichts anderes macht als eben sich um die Ausgabe zu kümmern. Ruft jede Operation diese Methode auf, so kann jede Änderung an dieser einen Stelle gemacht werden und wirkt sich automatisch auf alle Stellen im Programm aus.
Diese Methode könnte ja z.B. als Argument das Ergebnis bekommen. Somit muss addiere, substrahiere,... nur die Methode kennen. Sie berechnen ihr Ergebnis und übergeben es an die Methode, z.B.

Code:
// liegt in package1
public class Anzeige {

  // muss nicht direkt die GUI sein!
  public void zeigeErgebnis(int value) {
     gui.getResultLabel().setText((new Integer(value)).toString());
  }
}

// liegt in package2

import package1.Anzeige;

// oh gott, sollte dringend an den Namen arbeiten
class RechnerLogik {
  pubic void addiere(int a, int b) {
     // nur der Übersicht wegen
     int result = a + b;
    
     // hier wäre natürlich ein Singletion oder so sinnvoller
     new Anzeige().zeigeErgebnis(result);
  }

  pubic void subtrahiere(int a, int b) {
     // nur der Übersicht wegen
     int result = a - b;
    
     // hier wäre natürlich ein Singletion oder so sinnvoller
     new Anzeige().zeigeErgebnis(result);
  }
}

Natürlich kannst du die reine Anzeige in das gleiche Package packen wie die GUI. Alles was du an der Anzeigen ändern möchtest, änderst du dann in der Klasse Anzeige. Damit die Anzeige auch ein Element hat, auf dem etwas dargestellt wird, muss diese Klasse natürlich dann noch das Label (oder was auch immer) kennen. Auch hier ist kein direkter Zugriff nötig. Du kannst dir einfach setter und getter schreiben (hier reichen natürlich getter), die dir den Zugriff auf die Elemente kapseln. Hast du zum beispiel den getter getLabelXYZ(), so kann hier ein beliebiges Label nach aussen gereicht werden. Anders als beim direkt Zugriff auf die Variable, kann hier aber auch nur lesend auf diesen Wert zugegriffen werden. Du kannst dieses Label nicht durch ein anderes ersetzen! Natürlich kannst du zusätztlich die Sichtbarkeit getrennt einschränken (setter dann nur bei Nachfahren, getter dagegen öffentlich oder nur im Package,...)
Wenn du nun noch alles ein wenig mehr mit Interfaces designt hättest, kannst du auch leicht die Anzeige austauschen.

Hoffe ich hab wenigstens ein Teil so erklären können, dass es dir weiter hilft!

Gruß Der Unwissnede
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Klassen Fremde Klasse in GUI einbinden ? Java Basics - Anfänger-Themen 3
B Fremde Klassen benutzen Java Basics - Anfänger-Themen 21
Bastie Compiler-Fehler Fremde .class nutzen? Java Basics - Anfänger-Themen 12
B fremde klasse in eclipse projekt einbinden Java Basics - Anfänger-Themen 8
A auf fremde Klassen zugreifen Java Basics - Anfänger-Themen 3
I (fremde) IP mittels Applet auslesen Java Basics - Anfänger-Themen 6
X Fremde Klasse bzw. Methode aufrufen! Java Basics - Anfänger-Themen 9
G Fremde Anwendung starten Java Basics - Anfänger-Themen 2
C fremde Objekte in Objekten ;) Java Basics - Anfänger-Themen 2
J Packages erstellen Java Basics - Anfänger-Themen 7
S Daten/Klassen/Packages richtig updaten!? Java Basics - Anfänger-Themen 2
M Packages erstellen mit Java-Editor Java Basics - Anfänger-Themen 6
C Probleme mit dem Erstellen und Importieren von Packages Java Basics - Anfänger-Themen 6
A Exceptions und Packages Java Basics - Anfänger-Themen 6
M Probleme beim verwenden von Packages Java Basics - Anfänger-Themen 6
Mxxxt Übersicht Java-Packages Java Basics - Anfänger-Themen 3
D Zusätzliche Packages benutzen? Java Basics - Anfänger-Themen 6
C Java Packages Konvention Namensvergabe Java Basics - Anfänger-Themen 3
B eclipse und packages weiterentwickeln Java Basics - Anfänger-Themen 5
B Compiler-Fehler Packages fehlen? Java Basics - Anfänger-Themen 5
J Eclipse + Java + Packages importieren Java Basics - Anfänger-Themen 7
J eigene packages bzw klassen verwenden Java Basics - Anfänger-Themen 25
S Richtlinien wie man Classen in Packages organisieren soll? Java Basics - Anfänger-Themen 3
G Packages -> was bringen sie? Java Basics - Anfänger-Themen 4
V Java Packages Java Basics - Anfänger-Themen 4
O Funktionen dateiübergreifend mit Packages Java Basics - Anfänger-Themen 6
J Zugriff auf Variable vom typ (default) durch Importieren des Packages? Java Basics - Anfänger-Themen 5
D Javadoc für Packages oder ganze Projekte Java Basics - Anfänger-Themen 5
U Zugriff auf andere Packages Java Basics - Anfänger-Themen 10
S Problem mit Packages Java Basics - Anfänger-Themen 9
C Klassen Main-Routine in Packages? Java Basics - Anfänger-Themen 7
L Konsole und packages Java Basics - Anfänger-Themen 8
B Packages in Eclipse umbennen Java Basics - Anfänger-Themen 12
V Packages: Cannot find symbol Java Basics - Anfänger-Themen 12
Blindxantos Klassen in verschiedene Packages unterteilen Java Basics - Anfänger-Themen 2
B Wie funktioniert der Import von Dritt-packages in Eclipse? Java Basics - Anfänger-Themen 5
K Collections Problem beim import von Packages Java Basics - Anfänger-Themen 10
M Tief verschachtelte Packages Java Basics - Anfänger-Themen 7
Z CLASSPATH + Packages Java Basics - Anfänger-Themen 6
N packages und finden von Klassen Java Basics - Anfänger-Themen 2
J Packages in Jar-Datei Java Basics - Anfänger-Themen 7
D Packages verwenden und in eigenes Projekt integrieren Java Basics - Anfänger-Themen 3
S Anfängerproblem mit Packages Java Basics - Anfänger-Themen 4
J Anfängerfrage zu Grundlagen von Packages Java Basics - Anfänger-Themen 7
B Unterklassen, Packages Java Basics - Anfänger-Themen 3
F Dateipfade mit Packages Java Basics - Anfänger-Themen 7
R mit klassen-instanzen arbeiten in packages Java Basics - Anfänger-Themen 10
F OOP Wrapper ermöglicht Zugriff für andere Packages? Java Basics - Anfänger-Themen 6
T Javac und Packages Java Basics - Anfänger-Themen 4
B Fragen zur Initialisierung/Zuweisung der Variable + Packages erstellen Java Basics - Anfänger-Themen 4
braindump Packages in verschiedenen Unterverzeichnissen Java Basics - Anfänger-Themen 3
G Verschiedene Packages Java Basics - Anfänger-Themen 3
R wo befinden sich die packages? Java Basics - Anfänger-Themen 5
S 2 Packages Java Basics - Anfänger-Themen 14
D packages importieren Java Basics - Anfänger-Themen 3
I Frage zu Packages Java Basics - Anfänger-Themen 19
T Anagram Game - warum ist es auf 2 Packages aufgeteilt? Java Basics - Anfänger-Themen 3
S problem mit packages Java Basics - Anfänger-Themen 7
G Konventionen für die Bezeichnung von Packages Java Basics - Anfänger-Themen 4
M problem mit packages Java Basics - Anfänger-Themen 5
D Packages mit Wizard erstellen Java Basics - Anfänger-Themen 2
S Woher Packages bekommen? Wie installieren? (Netbeans) Java Basics - Anfänger-Themen 4
B Packages einfach kopieren? Java Basics - Anfänger-Themen 13
B Fehler beim einbinden eines Packages Java Basics - Anfänger-Themen 6
G Aufgabe mit Packages Java Basics - Anfänger-Themen 3
G erstes Arbeiten mit Packages Java Basics - Anfänger-Themen 2
H javac mit meheren packages Java Basics - Anfänger-Themen 2
G Aus package auf andere eigene packages zugreifen? Java Basics - Anfänger-Themen 7
E import Anweisung und Packages Java Basics - Anfänger-Themen 3
F Pfadfrage in Packages und jar-Archiven Java Basics - Anfänger-Themen 3
P packages verwenden Java Basics - Anfänger-Themen 3
D Probleme nach Einbindung einens neuen Packages Java Basics - Anfänger-Themen 5
T Packages erstellen und importieren? Java Basics - Anfänger-Themen 10
D Packages Java Basics - Anfänger-Themen 3
T Verständnisproblem packages/import Java Basics - Anfänger-Themen 9
P wohin muss ich die packages kopieren? Java Basics - Anfänger-Themen 12
T Erstellen eigener packages Java Basics - Anfänger-Themen 6
H Packages in JAR-Datei einbinden Java Basics - Anfänger-Themen 10
S Importieren in Packages Java Basics - Anfänger-Themen 11
C packages, jars - Verstaendnisfrage Java Basics - Anfänger-Themen 7
L Problem mit Packages Java Basics - Anfänger-Themen 5
L Eigene Packages importieren Java Basics - Anfänger-Themen 2
N Packages definieren bzw. zum Classpath hinzufügen Java Basics - Anfänger-Themen 4
A Packages und Vererbung Java Basics - Anfänger-Themen 5
S Packages verwenden Java Basics - Anfänger-Themen 7
T Nerv! Packages und Classpath Java Basics - Anfänger-Themen 2
H probleme mit import von eigenen packages Java Basics - Anfänger-Themen 4
C Packages... Java Basics - Anfänger-Themen 7

Ähnliche Java Themen

Neue Themen


Oben