Ausgabe einer ArrayList ensteht nur als Hashcode, nicht als Objekt

Miez

Mitglied
Hallo zusammen,

vielleicht ist hier ja jemand, der mit einen kurzen Tipp geben kann. Ich habe eine ArrayList (Name: freunde) implementiert, die Freunde speichert (Vorname, Name, Geburtsdatum, Adresse). Nun möchte ich die Liste ausgeben lassen.

Die Liste ist in eine Methode gepackt (getFreundesliste), damit ich sie woanders aufrufen kann und per GUI ausgeben. Das funktioniert alles....

Der Code ist

Java:
   public ArrayList getFreundesliste() {
            for (int i = 0; i < freunde.size(); i++) {
               Freund f = (Freund) freunde.get(i);
            }
        return freunde;
    }

Die Liste wird mir ausgegeben, allerdings sind die einzelnen Einträge nur Hashcodes,
also statt:
Beispielvorname, Beispielname, Beispieldatum, Beispieladresse erhalte ich Freund@46daef40 etc.

Ich glaube, es liegt daran, dass ich irgendwie nicht die Objekte ausgebe.
Hat jemand einen Tipp? Fehlt bei der for-Schleife noch etwas?

Vielen lieben Dank!
 
Wenn du ein Objekt auf der Konsole ausgibst, wird automatisch die toString() Methode aufgerufen. Wenn man die nicht überschreibt, greift die Standardimplementierung aus Object, die einfach den Klassennamen + hashCode ausgibt.

Spring, um eine schöne String-Darstellung zu erreichen solltest du die toString() Methode passend überschreiben.
 
Also erst einmal sollte der gegebene Code gar nichts ausgeben. Was soll der Code machen? Wenn Du - so wie der Name aussagt - nur die Freundesliste zurück geben willst, dann kann die Schleife ganz weg und ein return freunde; ist alles, was Du brauchst.

Wenn die Methode auch die Ausgabe machen sollte (das wäre aber dann doch eigentlich eine print Methode sein. Da wäre eine Schleife so wie Die vorhandene Schleife richtig. aber in der Schleife müsste dann noch eine Ausgabe sein wie System.out.println(f);
Zu dem Problem:
Es scheint, dass Du ein Freund einfach ausgibst. Um den String eines Objektes für die Ausgabe zu erhalten, wird die Methode toString() aufgerufen. Die toString() Methode von Object gibt immer den Klassennamen@Hashcode aus. Das erklärt die Ausgabe, die Du bekommst. Wenn Du eine andere Ausgabe bei der Ausgabe eines Freundes haben willst, dann musst Du in der Klasse Freund die toString() Methode überschreiben.
 
Danke werde ich gleich versuchen!

p.s. der Code gibt etwas aus, denn ich rufe die Methode mit einem JOptionsPane GUI auf, und bekomme dann in meinem kleinen Fenster die Liste der Hashcodes statt der Attribute von Freund. Aber danke für den Hinweis, das hatte ich vergessen zu kommunizieren

Hat geklappt, super, danke!
 
Zuletzt bearbeitet:
p.s. der Code gibt etwas aus, denn ich rufe die Methode mit einem JOptionsPane GUI auf, und bekomme dann in meinem kleinen Fenster die Liste der Hashcodes statt der Attribute von Freund. Aber danke für den Hinweis, das hatte ich vergessen zu kommunizieren
Dann kannst Du die Schleife dort komplett heraus nehmen nehme ich mal an. Denn die Schleife macht unter dem Strich nichts. Du brauchst dann vermutlich nur die Rückgabe der Liste der Freunde.

Und was auch noch auffällt: Habt Ihr das Thema Generics behandelt? Du verwendest eine ArrayList ohne Angabe eines generischen Typs, womit Du hier eine Typsicherheit weggibst was sich u.a. durch einen notwendigen cast in der Zuweisung in der Schleife.
 
Vielen Dank!
Wir haben ziemlich viel behandelt, u.a. Generics. Allerdings hat meine Uni nur einen vorab aufgenommenen Videokurs zur Verfügung gestellt ohne die Möglichkeit von Rückfragen. Nun ist ein Programm gefordert, und als Anfänger schwimme ich ein wenig ;-) Ich werde mich dann wohl nochmal mit den Generics auseinandersetzen, ich dachte, das sei für eine solche Aufgabenstellung nicht ganz so wichtig...
 
Nur, damit Du weißt, wie so etwas aussehen kann:
Java:
class XYZ {
    private List<Freund> freunde = new ArrayList<>();

    public void add(Freund freund) {
        freunde.add(freund);
    }

    public Freund get(int ix) {
        return freunde.get(ix);
    }

    public void zeigeFreunde() {
        for (Freund freund : freunde) { // for-each-Schleife
            System.out.println(freund); // wenn toString überschrieben wurde
        }
    }
}
 
Ah, da fällt mir noch ein: könnte ich prinzipiell meine for-Schleife so erweitern, dass sie, wenn keine Freunde in der Liste stehen, mittels try-catch eine Ausgabe wie: Sorry, you're alone oder sowas ausgibt? Oder muss ich das dann in eine extra Methode packen?

Und benötige ich das Generics, um sozusagen meiner Array List verschiedene Datentypen übergeben zu können? Momentan gebe ich auch das Geburtsdatum wie alles anders als String ein, aber das wäre natürlich als Datumsformat praktischer. Kann eine Array List verschiedene Datentypen enthalten wenn ich Generics verwende?
 
Du kannst einfach abfragen, wie viele Elemente in der Liste sind und dann kannst du entscheiden, ob du durch die Liste gehst oder ob du eine andere Meldung ausgibst.

Aber evtl. zeigst du einmal deinen Code (ruhig in einem Gespräch wenn du nicht zu viel öffentlich zeigen willst), denn irgend etwas stimmt noch nicht bei dem, was du bisher so zeigst ….

Ich bin auch gerade noch unterwegs, aber ich schreibe nachher noch kurz etwas mehr zu
  • Generics
  • Trennung von Ausgabe und Model
 
Ich schätze die Mühe sehr, sie müssen sich aber natürlich nicht so viel Zeit nehmen, werde selbst auch noch nach Generics recherchieren.
Freue mich aber natürlich über jeden Input.
So privat ist mein Code nicht ;-)

Aber was ist denn diese Gesprächsoption? Kann man eine (kostenpflichtige?) Beratung buchen oder wie funktioniert das?

Prinzipiell funktioniert sogar alles so wie es soll 🙂 Ich kann meine "Freunde" in einer txt-Datei speichern und wieder abrufen, kann diese durchsuche, Freunde hinzufügen, Freunde löschen, die Anzahl der Freunde ausgeben, eine Liste der Freunde mit individuellem ID-Zähler ausgeben... und das ganze sogar grafisch mit JOption Pane.

gerade beiße ich mir eben an diesen vermeintlichen Kleinigkeiten (oder auch nicht so kleinen Fragen) die Zähne aus....
 
Zuletzt bearbeitet:
Generics dienen der Typsicherheit. Eine List (ohne Typparameter, sog. raw type) kann beliebige Objekte aufnehmen, deswegen liefert get() ein Object, das Du auf Freund casten musst. Wenn man aber etwas in eine Liste steckt, das sich nicht zu Freund casten lässt, fliegt beim Versuch, auf Freund zu casten eine Exception. Das passiert aber erst zur Laufzeit. Mit Generics gibt man dem Compiler konkrete Informationen zum Typ, und der prüft das gnadenlos ab, so dass derartige Fehler schon zum Zeitpunkt der Übersetzung verhindert werden.
 
Aber was ist denn diese Gesprächsoption? Kann man eine (kostenpflichtige?) Beratung buchen oder wie funktioniert das?
Das ist einfach nur im Forum eine private Nachricht. Einfach einmal auf den Namen klicken und dann im PopUp auf den Knopf "Gespräch beginnen".

Bezüglich Generics nur eine absolute Minimal-Einführung um Klassen, die Generics anbieten, zu nutzen. Eine Recherche und auch ein "selbst probieren" ist wichtig, um dann auch Generics in eigenen Klassen zu nutzen. Aber den Aspekt behandel ich nicht. Aber ehe es los geht, erst noch ein anderes Thema: Wie kann man es selbst lernen?

Du hast angesprochen, dass die Lernunterlagen evtl. nicht ausreichend sind. Daher als erstes ein Hinweis auf ein Buch, das Du Dir einmal ansehen kannst (Findest Du mit etwas Glück in der Bibliothek der Uni!):
Java von Kopf bis Fuß - das ist ein Buch, welches sehr bildlich Java erklärt. Es werden nicht die neuesten Features erläutert, aber Du bekommst ein solides Fundament der Sprache Java. Das Buch ist wohl das am meisten empfohlene Buch für Einsteiger.
Wenn Java dann soweit verstanden wurde, dann ist das Buch "Entwurfsmuster von Kopf bis Fuß" eine sehr lohnende Lektüre.


Generics
Mit Generics kannst Du genauer spezifizieren, was eine Klasse für andere Klassen verwenden soll. Die ArrayList bei Deinem Code ist ein gutes Beispiel:
Arraylist freunde = new ArrayList();
Hier hast Du dann jetzt eine Liste, in der Du beliebige Dinge speichern kannst. Du kannst da also Instanzen von deiner Klasse Freund hinein packen aber auch beliebige andere Instanzen. Das wird also nicht überprüft und sorgt dafür, dass Du nach dem Auslesen eines Elements diesen Cast zu Freund gebraucht hast. Und wenn Du da in der Liste irgendwo auch ein Auto abgelegt hast, dann fliegt da leider eine Exception. Das kann durch Angabe einer Typvariable genau spezifiziert werden:
Arraylist<Freund> freunde = new ArrayList<>();
(Beim der Initialisierung kann der Typ weggelassen werden - er nimmt automatisch den Typ von der Deklaration der Variable. Aber auch da könntest Du <Freund> schreiben.)
Jetzt kannst Du nur noch Instanzen von Freund (oder davon abgeleitet) ablegen. Und bei dem Aufruf von get ist klar: Es wird ein Freund zurück gegeben, daher brauchst Du diesen Cast nicht mehr.

Generell sollte man hier immer eine Typ spezifizieren, damit man bezüglich der Typen sicher ist. Denn jetzt kann der compiler meckern, wenn Du versuchst, ein Auto zuzuweisen.

Trennung UI von Model
Du solltest die Ein- und Ausgabe nicht mit dem sogenannten Model vermengen. Wenn Du also eine Klasse Freundesliste hast, dann hält die nur die Freunde vor, d.h. Du hast nur Methoden um Freunde hinzu zu fügen, zu entfernen oder zu suchen oder so. Aber Du hast keine Ausgabe oder so. Das hat den Vorteil, dass Du diese Klassen universell nutzen kannst. Es ist egal, ob Du eine Konsolenanwendung, UI-Anwendung oder Web Anwendung hast.
Wenn Du also jetzt einen Freund ausgeben willst (egal ob auf der Konsole oder in einem Dialogfenster oder so), dann ist das eine eigene Klasse. Und da kann dann eine Methode sein wie print oder printFreund. Also etwas wie:
Java:
public class FreundIO {
    public void print (Freund freund) {
        StringBuilder output = new StringBuilder();
        output.append(freund.getVorname());
        output.append(", ");
        output.append(freund.getNachname());
        System.out.println(output.toString());
    }
}

Das wären so die Punkte, die ich einmal anmerken und etwas beschreiben wollte.
 
Wow, vielen Dank! Ich hatte Grundkurs Programmieren in Java von Dietmar Ratz und weiteren Autoren als Buch zum Kurs gelesen.
Ihre Erklärung leuchtet mir ein.
Ich werde mich nochmal gründlich in das andere Buch einlesen 🙂
 
Hallo, hier bin ich nochmal mit einer Frage 🙂

Ich hab mit Ihren Erklärung alles gut hinbekommen, das Programm schnurrt 🙂
Jetzt bin ich noch am Feinschliff....

Ich hab mich gefragt, ob ich wenn ich meine Freundesliste ausgebe, auch eine Ausgabe machen kann wie "Du bist allein", sollten sich aktuell keine Freunde-Objekte in der Liste befinden....

Ich hab hiermit experimentiert, aber das war wenig fruchtbar.....


Java:
case 6:
                    JOptionPane.showMessageDialog(null, "Freundesliste:" + ak.getFreunde());
                    boolean ergebnisZwei = ak.getFreunde();
                    if (!ergebnisZwei) {
                        JOptionPane.showMessageDialog(null, "Du bist allein!");
                    }
                    break;

das gibt Fehler.

Zur Erklärung: wenn ich nur die Freundesliste ausgebe, dannn bekomme ich die mit getFreunde ohne Probleme. Aber wie stelle ich das an, dass bei einer leeren Liste eine String Message ausgegeben wird?

Vielen Dank!
 
Hier wäre mein genereller Tipp: Überlege Dir den genauen Ablauf und schreibe diesen in Worten auf. Und dann setze es erst um.

Hintergrund ist, dass die Logik schon unsinnig ist. Unabhängig davon, dass der Code nicht übersetzt: Du willst doch nicht erst den MessageDialog haben: "Freundesliste: " um dann da nach noch eine weitere Mitteilung "Du bist allein!" zu bekommen.

Daher: Schreibe GENAU auf, was Du machen willst. Das könnte also sein:
Wenn Anzahl Freunde == 0
dann: Nachricht: "Du bist alleine"
sonst: Nachricht: "Freundesliste: " gefolgt von Liste aller Freunde.

Und das kannst Du dann umsetzen. Du musst also schauen, dass Du eine Methode hast, um die Anzahl der Freunde anzufragen. Evtl. hast Du das schon oder Du musst sowas dann noch einbauen ...

Zu dem Code:
a) Nutz bitte Variablen, die etwas aussagen! ak oder ergebnisZwei sagen nichts aus!
b) getFreunde() wird vermutlich einen String zurück geben. (Oder auch gerne eine Liste mit Freunden oder so). Das kannst Du nicht in ein boolean speichern. Das dürfte vermutlich der Fehler sein, von dem Du sprichst. (Hier wäre es in Zukunft hilfreich, wenn Du uns auch den genauen Fehler mitteilen würdest)
 

Neue Themen


Zurück
Oben