Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.
11.2 Probleme, die buckets zu füllen
Hi,
was ich zum einen sowieso mal wieder nicht verstehe, ist,
wieso hat z.B. cleanStrings als Parameter und Rückgabewert
List. List ist ein Interface und keine Klasse!
Entsprechend verwirrt mich schon mal,
dass die vorgegebene Zeile
List[] buckets = new List[63];
funktioniert, oder zumindest der compiler nicht schimpft.
Ich hab nun eine Lösung, die kompiliert,
aber wenn ich testweise von außen das sortieren aufrufe,
bekomme ich für das Befüllen der Buckets eine NullPointerException
für meine Zeile
buckets[bucketNumber].add(s); (s ist der String)
add(s) ist nicht das Problem, gleicher Fehler tritt auch auf, wenn ich testweise nur size() dazu aufrufe,
auch testweise mal 41 statt bucketNumber ändert nix, bucketNumber berechnen ist also nicht der Fehler.
d.h. z.B. bucket[41] ist nicht als List (bzw. mit den zugehörigen Methoden) ansprechbar.
wenn ich was “vernünftiges” definiere, z.B. eine ArrayList, dann kann ich die ja mit add() befüllen,
wird ja auch vom Konstruktor schon mal mit einer Anfangslänge von 10 erzeugt.
bei List gibts naturgemäß (Interface!) auch keinen Konstruktor, wo ich mal nachschauen könnte,
wie das nach Neuerzeugung ausschaut.
Kann mir jemand hier auf die Sprünge helfen?
a) wieso klappt das überhaupt größtenteils, wenn man List wie eine Klasse benutzt?
b) wieso klappt es nicht mehr beim bucket-befüllen?
Danke!
Das ist beim Rückgabetyp eigentlich ähnlich wie beim Typ von Variablen. Die Methode kann hier ein Objekt einer beliebigen Klasse zurückgeben, die dieses Interface implementiert. Du könntest hier also z.B. eine [m]ArrayList[/m] oder auch eine [m]LinkedList[/m] zurückgeben, da beide [m]List[/m] implementieren.
Du erzeugst hier auch keine Objekte vom Typ [m]List[/m] (was ja nicht geht, da es sich hierbei um ein Interface handelt), sondern ein Array, das, wie schon beim Rückgabetyp beschrieben, Objekte beliebiger Klassen, die dieses Interface impementieren, speichern kann.
[m]buckets[bucketNumber][/m] wird dann wohl [m]null[/m] sein. Ich nehme jetzt einfach mal an, dass du in das Array noch nichts geschrieben hast, also jeder Eintrag noch das standardmäßige [m]null[/m] ist.
Hier machst du wahrscheinlich auch ein [m]new ArrayList[/m] und kein [m]new ArrayList[n][/m], was eben ein gewaltiger Unterschied ist. [m]ArrayList l = new ArrayList[1]; l[0].add(„foo“);[/m] würde dir genauso um Ohren fliegen. Wie du das fixt, darfst du dir jetzt noch selber überlegen.
Ist mir in dem Fall auch nicht klar, warum keine Generics verwendet wurden. Nachdem du aber weißt, was für eine „richtige Klasse“ du reingesteckt hast, wird bei einem anschließendem cast auch nichts kaputt gehen. Guter Stil ist das nicht.
Das funktioniert (bis auf die Java-Generic-eigenheiten) relativ problemlos, du erzeugst ja nur einen Array vom Typ List mit leeren Elementen, also Nullreferenzen.
Damit ist dann auch klar, warum du die NullPointerException bekommst - du musst die Elemente des Arrays noch initialisieren. Da du den Array mit dem Interfacetyp initialisiert hast, kannst du dir die Implementierung noch aussuchen. Aber du musst halt auch eine auswählen und die Listenelemente damit initialisieren, dann kannst du auch der Liste etwas hinzufügen.
Natürlich kannst du nicht nachschauen, wie ein Interface nach der Erzeugung aussieht, weil das ja von der gewählten Implementierung abhängt.
PS: verdammt zu langsam xD
Vielen Dank für die Antworten!
jetzt hab ich es damit (soweit ich sehen kann…) hinbekommen!
Wieso sollte cleanStrings generische Parameter haben?
Oder meinst du sowas wie
[m]public static <T extends Collection> T cleanStrings(T c)[/m] ?
Das hätte man machen können, hätte imho aber zu mehr Verwirrung geführt und hat seine ganz eigenen Probleme. Ich sehe auch den Vorteil nicht direkt, weil [m]List[/m] alles kann, was man für die Methode braucht.
Was für andere Probleme hat es denn? Mit der Generic Variante spart man sich halt die Casts. Ja, in Java müssen sie trotzdem ausgeführt werden, aber ich hab sowas nicht gern im Code. Mit der Generic Variante bekommt man eben gleich den richtigen Typ der Liste. Theoretisch könnte man ja auch in der Methode eine andere Liste anlegen, die das List-Interface anbietet, und returnen. Dann geht der Cast kaputt.
Das mit der Verwirrung mag zwar teilweise stimmen, aber Generics gehören doch zum Stoff und so sind halt wieder andere Leute verwirrt. Zumal sich ja am Aufruf durch die automatische Typinferenz nichts ändert.
[quote=L. F. Ant]
Was für andere Probleme hat es denn?[/quote]
Primär, dass man nicht die Option hat, eine neue Liste zu erstellen, weil man keine Ahnung hat, was man zurückgeben soll.
Welchen Cast eigentlich? Das Entfernen der Füllzeichen der Strings ist der letzte Schritt des Sortierens und die Sortiermethode selbst gibt ebenfalls [m]List[/m] zurück. Man muss das gar nicht mehr anfassen.
Trotzdem hast du natülichh recht dass man die Signaturen auch anders wählen kann und ursprünglich waren auch keine der „Hilfsmethoden“ vorgegeben. Ich habe mich aber entschiedenen die mit reinzunehmen, weil man so auf Teilfunktionalitäten auch mal ein paar Pünktchen geben kann und es dem einen oder anderen vielleicht dabei hilft, ein Gefühl für das Auslagern von Funktionalität zu entwickeln.
Da hatte ich nicht genau genug in die Aufgabe geschaut
Ich habe mich aber entschiedenen die mit reinzunehmen, weil man so auf Teilfunktionalitäten auch mal ein paar Pünktchen geben kann und es dem einen oder anderen vielleicht dabei hilft, ein Gefühl für das Auslagern von Funktionalität zu entwickeln.
Das ist natürlich aus studentischer und Tutorsicht sehr lobenswert