Problem mit der Serialisierung

Bitte aktiviere JavaScript!
Hallo,
ich habe folgendes Problem:
Ich will ein Spiel machen, in welchem es einen Highscore geben soll. Dieser soll auch gespeichert werden, wenn ich das Programm beende.
Also habe ich einmal in die Klasse, in der der Highscore gespeichert wird, Serializable implementiert. In einer zweiten Klasse habe ich nun sozusagen den Speichervorgang niedergeschrieben. (Also, dass die Variable in ein File geschrieben wird, und auch ausgelesen werden)
Nach jeder Runde wird der Highscore nun in das File gespeichert. (Also müsste er eigentlich)
Wenn ich das Spiel jetzt aber schließe und neustarte und auf das File zugegriffen werden soll, ist der Highscore nicht gespeichert.
Was habe ich vergessen?
DerSophist
 
Speicherung:
Java:
package com.company;

import java.io.*;

public class SpeicherVorgang
{
    public static void writeHighscoreToFile () throws IOException
    {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("SpielDaten.bin"));
        oos.write(Var.Highscore);

    }

    public static void readHighscoreFromFile () throws IOException
    {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("SpielDaten.bin"));
        Var.Highscore = ois.read();

    }

    public SpeicherVorgang() throws IOException
    {
        readHighscoreFromFile();
    }
}
Der Highscore:
Java:
public class Var implements Serializable
{
     static int Highscore;
}
In einer anderen Klasse des Spiels:
Java:
if (Var.leben == 0) {
    if (Var.schrott > Var.Highscore)
    {
        Var.Highscore = Var.schrott;
        try {
            SpeicherVorgang.writeHighscoreToFile();
        } catch (IOException e) {
            System.out.println("Etwas hat nicht geklappt!");
        }
    }
In der Main:
Java:
package com.company;

import java.io.IOException;

public class Main 
{
    public static void main(String[] args) throws IOException {
   // write your code here
        new Gui(); //die Gui wird erstellt, wenn das Programm startet
        new Var(); //die Var wird erstellt, wenn das Programm startet
        new Label(); //das Label wird erstellt, wenn das Programm startet
        new KeyHandler(); //der KeyHandler wird erstellt, wenn das Programm startet
        new Background(); //das Background-Verhalten wird erstellt, wenn das Programm startet
        new PlayerMovement();
        new FlammenAnimation();
        new GegnerMovement();
        new SchrottMovement();
        new GegnerKollision();
        new SchrottKollision();
        new Explosion();
        new ActionHandler();
        new SpeicherVorgang();
    }
}
 
Zuletzt bearbeitet:
ich habe folgendes Problem:
Klasse Var mit statischen Variablen... :mad: Hast Du das zufällig aus einem YouTube-Tutorial übernommen? Der ganze Aufbau erinnert zumindest sehr daran --> Tonne. Die Highscore wird über mind. drei Klassen verteilt verwaltet.

Vermutung: irgendwo wird beim Starten die Highscore rausgeschrieben (ggf. auch vorher noch auf 0 gesetzt) und damit die gespeicherte Datei überschrieben, bevor sie dann am Ende wieder geladen wird.
 
Davon abgesehen: Die Klasse, die das Highscore Attribut besitzt, muss in dem Fall nicht Serializable implementieren. Du willst ja nicht die Klasse an sich serialisieren. Vielmehr willst du nur den Highscore (einen einfachen int-Wert) abspeichern.

Ist der Fehler nicht vielmehr, dass er den zugehörigen Stream nach dem schreiben nicht schließt? Oder ist es gerade zu früh zum denken? *grübel*
Edit: (davon abgesehen ob es der Fehler ist oder nicht: Alles Streams, die du selber öffnest, solltest du auch wieder schließen. Entweder über den Aufruf der close() Methode oder über (ab Java 7) try-with-resource Blöcke)

Wie @mihe7 schon sagte .. lass die Finger von diesem YouTube-Tutorial (Name des Kanals nenn ich mal lieber nicht) .. das hat absolut gar nichts mit OOP zu tun ..
 
st der Fehler nicht vielmehr, dass er den zugehörigen Stream nach dem schreiben nicht schließt? Oder ist es gerade zu früh zum denken? *grübel*
Beim Schließen des Programms müsste der Stream automatisch geschlossen werden. Aber ganz ehrlich: bei diesem - nennen wir es mal - "Code" habe ich gar keine Lust, mir großartig Gedanken über die Ursachen zu machen :)

Dieses Video (oder wo das Zeug sonst noch rumgeistert) nervt einfach nur.
 
Such einfach nach Pong programmieren und Du wirst fündig :D
Oh jee. Ich gebe Dir Recht: Ich wollte das gar nicht finden :) Ich wusste er nur nicht, ehe ich es gefunden habe. Da überschlagen sich die Kommentare ja von wegen "Super Tutorial" und so ...

Irgendwie macht mich das jetzt fast sprachlos.

bei diesem - nennen wir es mal - "Code" habe ich gar keine Lust, mir großartig Gedanken über die Ursachen zu machen :)
So ging es mir schon Gestern Abend als ich es gesehen hatte. Ich wollte Antworten und wusste schon nicht, wo ich anfangen sollte. Und eine Antwort a.la. "Geh und lern Java von einer vernünftigen Quelle" mit paar Links zu Java ist auch eine Insel und so schien mir nicht wirklich hilfreich und ein "Buch schreiben" über static wollte ich hier im Forum jetzt auch nicht und darauf wäre es wohl hinaus gelaufen hätte ich gestern geantwortet....
 
Oh jee. Ich gebe Dir Recht: Ich wollte das gar nicht finden :) Ich wusste er nur nicht, ehe ich es gefunden habe. Da überschlagen sich die Kommentare ja von wegen "Super Tutorial" und so ...

Irgendwie macht mich das jetzt fast sprachlos.


So ging es mir schon Gestern Abend als ich es gesehen hatte. Ich wollte Antworten und wusste schon nicht, wo ich anfangen sollte. Und eine Antwort a.la. "Geh und lern Java von einer vernünftigen Quelle" mit paar Links zu Java ist auch eine Insel und so schien mir nicht wirklich hilfreich und ein "Buch schreiben" über static wollte ich hier im Forum jetzt auch nicht und darauf wäre es wohl hinaus gelaufen hätte ich gestern geantwortet....
Was ist denn so schlecht an dem Tutorial? Ich bin relativ neu mit Java (Syntax und ähnliches kann ich, muss aber noch die ganzen Klassen und generell Programmieren mit Java kennenlernen).
Ich dachte: Es funktioniert, also kann das ja alles nicht so schlecht sein...
Und übrigens: Es ging hier nicht darum, wie ich dieses Spiel programmiert habe, sondern um die Serialisierung.
Ich muss ehrlich sein, als ich auf den Discord von dem "Tutorial-Macher" gegangen bin, wurde mir bei meinen Fragen sehr nett, schnell, hilfsbereit und auch weiter helfend geantwortet. So etwas hätte ich mir hier auch mehr gewünscht...
Bis jetzt hat mir noch keine Antwort geholfen mein Problem zu lösen...
 
Beim Schließen des Programms müsste der Stream automatisch geschlossen werden. Aber ganz ehrlich: bei diesem - nennen wir es mal - "Code" habe ich gar keine Lust, mir großartig Gedanken über die Ursachen zu machen :)

Dieses Video (oder wo das Zeug sonst noch rumgeistert) nervt einfach nur.
Ich dachte der Sinn dieses Forums ist, fragen zu stellen. Wenn du keine Lust hast, meine Fragen zu beantworten, dann mach es halt nicht, ich würde mich nur sehr darüber freuen, wenn mir jemand bei meinem Problem weiterhelfen kann.
Das ist mein erstes richtiges Java-Projekt und sag mir, wie hättest du dich gefühlt, wenn du jemandem eine Frage gestellt hättest, und er hätte einfach nur gesagt: "Dein Code ist ja so ne Scheiße, da habe ich gar keine Lust dir zu helfen."
Das führt doch zu nichts. Das hat nichts mehr mit konstruktiver Kritik zu tun oder weiterhelfen zu tun, denn geholfen hat es mir nicht. Meckern, meckern, meckern...
Vielleicht solltest du mal aus deinem Programmierkeller herauskommen und dich in menschlicher Konversation und Hilfsbereitschaft üben ;).
 
Das Tutorial macht genau die Dinge, die man in einer Objektorientierten Sprache nicht will, zB das Arbeiten mit einer Var-Klasse, die alle Variablen enthält, das ist ein absolutes Antipattern. Arbeiten mit Klassen (bzw Objekten) lernt man dabei eben nicht sinnvoll, sondern hauptsächlich Syntax und imperatives Denken.
Einige Mitglieder hier sind (verständlicherweise) entsprechend frustriert, weil man das immer wieder sieht, und es immer wieder die selben Fehler produziert.
Bevor man mit GUI anfängt, sollte man bereits die Grundlagen drauf haben, und die schließen Objektorientiertes Arbeiten ein. Das Tut macht genau das Gegenteil - mit GUIs Arbeiten, ohne entsprechende Grundlagen, und dabei gefühlt alle falsch machen, was möglich ist.


Eine Vermutung, was der Grund für den Fehler ist, hat @mihe7 ja schon geäußert (und ich bin der selben Meinung) - und der Fehler kommt durch die Struktur, die man in diesen Tutorials lernt. In dem gezeigten Code findet sich der Fehler nicht direkt, der liegt irgendwo anders, da alles public und static ist kann der irgendwo im Programm liegen - du musst einfach mal selbst gucken, wo der Highscore verändert wird.
 
Das Tutorial macht genau die Dinge, die man in einer Objektorientierten Sprache nicht will, zB das Arbeiten mit einer Var-Klasse, die alle Variablen enthält, das ist ein absolutes Antipattern. Arbeiten mit Klassen (bzw Objekten) lernt man dabei eben nicht sinnvoll, sondern hauptsächlich Syntax und imperatives Denken.
Einige Mitglieder hier sind (verständlicherweise) entsprechend frustriert, weil man das immer wieder sieht, und es immer wieder die selben Fehler produziert.
Bevor man mit GUI anfängt, sollte man bereits die Grundlagen drauf haben, und die schließen Objektorientiertes Arbeiten ein. Das Tut macht genau das Gegenteil - mit GUIs Arbeiten, ohne entsprechende Grundlagen, und dabei gefühlt alle falsch machen, was möglich ist.


Eine Vermutung, was der Grund für den Fehler ist, hat @mihe7 ja schon geäußert (und ich bin der selben Meinung) - und der Fehler kommt durch die Struktur, die man in diesen Tutorials lernt. In dem gezeigten Code findet sich der Fehler nicht direkt, der liegt irgendwo anders, da alles public und static ist kann der irgendwo im Programm liegen - du musst einfach mal selbst gucken, wo der Highscore verändert wird.
Wirklich weiterhelfen tut mir das nicht...
 
Okay, der letzte Satz noch mal anders: irgendwo in deinem Programm wird der Highscore gesetzt (an einer hier nicht gezeigten Stelle), das passiert vermutlich nach dem Laden des gespeicherten Highscores und überschreibt diesen daher.

Entweder du zeigst den ganzen Code, oder du muss selber suchen. Wirklich helfen kann da sonst keiner, der Code oben zum Schreiben/lesen ist an sich erstmal korrekt, der Fehler liegt wie gesagt woanders :)
 
Okay, der letzte Satz noch mal anders: irgendwo in deinem Programm wird der Highscore gesetzt (an einer hier nicht gezeigten Stelle), das passiert vermutlich nach dem Laden des gespeicherten Highscores und überschreibt diesen daher.

Entweder du zeigst den ganzen Code, oder du muss selber suchen. Wirklich helfen kann da sonst keiner, der Code oben zum Schreiben/lesen ist an sich erstmal korrekt, der Fehler liegt wie gesagt woanders :)
Die Variable Highscore bzw. der SpeicherVorgang kommt nirgendwo anders vor... könnte das der Fehler sein?
 
Sicher, dass dir Variable nirgendwo benutzt wird? Wenn du den Highscore nirgendwo benutzt ist klar, warum du nicht siehst, dass er gespeichert wurde...



Das Einlesen wird schon ausgeführt (wenn auch auf denkbar schlechteste Weise), das kannst du im Zweifel auch einfach mit einem System.out.print testen.
 
Ich dachte der Sinn dieses Forums ist, fragen zu stellen. Wenn du keine Lust hast, meine Fragen zu beantworten, dann mach es halt nicht, ich würde mich nur sehr darüber freuen, wenn mir jemand bei meinem Problem weiterhelfen kann.
Das ist mein erstes richtiges Java-Projekt und sag mir, wie hättest du dich gefühlt, wenn du jemandem eine Frage gestellt hättest, und er hätte einfach nur gesagt: "Dein Code ist ja so ne Scheiße, da habe ich gar keine Lust dir zu helfen."
Das führt doch zu nichts. Das hat nichts mehr mit konstruktiver Kritik zu tun oder weiterhelfen zu tun, denn geholfen hat es mir nicht. Meckern, meckern, meckern...
Vielleicht solltest du mal aus deinem Programmierkeller herauskommen und dich in menschlicher Konversation und Hilfsbereitschaft üben ;).
Da hast Du einige Dinge gewaltig missverstanden. Zunächst einmal ging es in meiner Antwort an @Robat nicht speziell um Deinen Code (von dem sieht man ja kaum was), sondern um den Aufbau des Codes aus dem "Tutorial". Wenn Du auf diese Weise die Serialisierung einbaust, verteilst Du den Spaß über mehrere Stellen und daher die Vermutung, dass Du irgendwo beim Öffnen der Anwendung die Datei überschreibst. Du hast aber zu wenig Code gezeigt, als dass man das mit Sicherheit sagen könnte. So könnte es sein, dass der Code, den Du mit "In einer anderen Klasse des Spiels" zitierst, beim Aufruf ausgeführt wird, zu diesem Zeitpunkt die Bedingungen erfüllt sind und daher die Datei überschrieben wird.

Abgesehen davon: Dir ist sicher mehr geholfen, wenn Dich jemand darauf aufmerksam macht, dass Du den grundsätzlich falschen Weg gehst, als Dir auf diesem Weg nur bei der Lösung eines akuten Problems zu helfen.
 
Also mal einfach von Anfang an:

a) Kritik an dem Tutorial solltest Du nicht auf Dich beziehen.

b) Was an dem Tutorial schlecht ist: Java ist eine Objektorientierte Sprache. Daher sollte man verstehen, was eben Objekte sind. Und dazu gehört, das man dann auch z.B massiv auf das Schlüsselwort "static" verzichtet. Anfängern hier im Forum empfehlen wir oft, auf dieses Schlüsselwort komplett (bis auf das "static void main") zu verzichten. Denn das verhindert nach meiner Erfahrung massiv die Erlernung einer Objektorientierten Sprache.

c) Dein Code - mögliche Fehler.
c1) Eine Vermutung ist, dass Du in der Logik etwas falsch machst. Evtl. stimmt die Reihenfolge von Aufrufen nicht oder etwas, das Du gerne aufrufen möchtest, wird nicht aufgerufen. Hier bietet sich die Nutzung eines Debuggers an. Oder wenn Dir das noch zu kompliziert ist: Bau mehr Ausgaben ein.
c2) Die Vermutung, die auch geäußert wurde, ist, dass Du die Daten in einen Stream schreibst. Dieser puffert die Daten zwischen (und schreibt diese nicht sofort) und dann kommt der Garbage Collector und zerstört das Objekt, ehe die Daten geschrieben werden konnten.

d) Dein Code - was daran unschön ist (und damit eine direkte Kritik an dem Tutorial ist!)

Nehmen wir uns nur einmal die main Methode um zu sehen, was die Applikation macht:
Java:
    public static void main(String[] args) throws IOException {
   // write your code here
        new Gui(); //die Gui wird erstellt, wenn das Programm startet
        new Var(); //die Var wird erstellt, wenn das Programm startet
        new Label(); //das Label wird erstellt, wenn das Programm startet
        new KeyHandler(); //der KeyHandler wird erstellt, wenn das Programm startet
        new Background(); //das Background-Verhalten wird erstellt, wenn das Programm startet
        new PlayerMovement();
        new FlammenAnimation();
        new GegnerMovement();
        new SchrottMovement();
        new GegnerKollision();
        new SchrottKollision();
        new Explosion();
        new ActionHandler();
        new SpeicherVorgang();
    }
Du erstellst eine ganze Reihe an Instanzen, aber keine Instanz scheint Dich wirklich zu interessieren, denn die erstellten Instanzen speicherst Du nicht.
Was mich daran massiv stört ist:
Das Erstellen einer neuen Instanz soll nur eine neue Instanz erzeugen. Wenn ich sage: Ich habe hier einen Bauplan von einem Haus, das Haus baue ich mir. Dann wird lediglich das Haus gebaut. Und danach möchte ich das erzeugte Haus haben. Bei Deinem Code ist das: Bau mir ein neues Haus und dann schmeiss es direkt weg.

Dann ist das "new House()" einfach ein erzeugen eines neuen Hauses. Da sind erst einmal keine Aktionen inbegriffen wie: Ich gehe in die Küche und koche eine Gulasch. Klar, das kann man technisch machen. Aber wenn ich jemandem sage "Ich baue mir ein Haus", dann erwartet niemand in dieser Aussage, dass ich einen Topf Gulasch koche. ==> Jemand der den Code sieht, will ja wissen, was in dem Code passiert. Und das sieht man in dem Code nicht, weil Du Aktionen in dem Construktor zu verstecken scheinst.

Also konkretes Beispiel wäre z.B. ein JFrame. "new JFrame()" erzeugt ein JFrame Objekt. Aber damit wird noch nichts gemacht. Das wird noch nicht angezeigt oder so. Keine versteckten Aktionen sind im "new Frame()" enthalten.

Also nur noch einmal zum Verständnis:
Klassen sind vergleichbar mit Bauplänen. Mit den Bauplänen erzeugst Du Objekte und diese nutzt Du. Also Du nutzt den Bauplan Notizblock um einen Notizblock zu erzeugen. Und en erzeugten Notizblock nutzt Du dann um da was rein zu schreiben. Du fängst doch nicht an, auf dem Bauplan rum zu kritzeln!

Dann weiter zum Verständnis: Deine Klasse Var hat nur einen Inhalt: eine statische Variable. Es macht also keinen Sinn, davon eine neue Instanz zu erzeugen. ein "new Var()" ist also einfach sinnlos. Das ist so etwas wie: Hier ist ein leerer Bauplan - auf dem habe ich zwar etwas notiert, aber sonst ist er einfach leer. Nun bau mir bitte nach diesem Bauplan ein neues Objekt ....
(Und da Du eine Instanzen davon erzeugst, ist - wie schon erwähnt wurde - das Serializable Sinnlos. Du willst sozusagen, dass die Objekte, die vom leeren Bauplan erzeugt werden, auch mit der Post versendet werden können.)

Ein Punkt, der auch wichtig ist, weil es ein mögliches Problem sein könnte:
In Java gibt es einen Müllmann (Garbage Collector). Der geht regelmäßig alles durch und sucht nach Objekten, die niemand mehr in der Hand hält. Und die zerstört er einfach.
Wenn Du also ein Objekt erzeugst, dann solltest Du es immer "in der Hand" behalten. Das bedeutet unter dem Strich, dass ein Thread auf dieses Objekt zugreifen können muss. Das muss nicht direkt sein - das geht auch über Umwegen. Also wenn ein Thread ein Objekt kennt, dass das fragliche Objekt kennt dann ist das auch ok.
Und dann das Problem mit dem BufferedStream:
Du willst etwas wegbringen. Aber damit Du nicht für jedes Paket extra zur Post rennen musst, hast Du eine Kiste, und in die wirfst Du alle Pakete. Und hin und wieder bringst du dann alle Pakete aus der Kiste zur Post. Nun mit dem, was ich davor geschrieben haben: Du wirfst es in die Kiste, aber dann interessiert dich die Kiste nicht mehr. Dann kommt der Müllmann und wirft die Kiste mit allen Paketen in den Müll - und dann kommen die Pakete nie zur Post.

Konkret bedeutet dies:
Java:
public static void writeHighscoreToFile () throws IOException
    {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("SpielDaten.bin"));
        oos.write(Var.Highscore);
    }
Du erzeugst eine Variable oos und rufst write auf. Danach ist die Methode zu Ende und damit die Instanz in oos vergessen und wird ein Fall für den Müllmann (Garbage Collector). So das, was Du geschrieben hast mit write noch nicht auf die Platte geschrieben hast, bedeutet dies, dass es weg ist.

Die Lösung ist hier einfach und eines der Grundprizipien von Java: Es gibt ein Interface AutoClosable, welches von Streams implementiert wird. Und die einfache Regel wurde schon genannt: Wenn ein Objekt AutoClosable implementiert, dann sollte man dieses schließen. Java hat dafür sogar extra ein Konstrukt: Try with ressources. Damit sähe der Code dann so aus:
Java:
public static void writeHighscoreToFile () {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("SpielDaten.bin"))) {
            oos.write(Var.Highscore);
        } catch (IOException ex) {
            System.err.println("Couldn't write highscore: " + ex.getMessage());
            ep.printStackTrace();
        }
    }
Nebenbei noch ein paar Dinge mehr eingebaut:
- Java Coding Style: { gehört in die gleiche Zeile.
- das throws habe ich raus genommen. Gibt doch keinen Grund, das weiter zu reichen ....
- Wenn exception, dann immer alles Ausgeben. Also mindestens die Message und den StackTrace! Eine einfache Aussage wie "Da ist was schief gelaufen" hilft nicht wirklich weiter...
- Und natürlich das try with ressources

e) Meine Empfehlung
Geh ein Lehrbuch durch. Java ist auch eine Insel ist frei und nicht schlecht. Evtl. gibt es auch auf YouTube vernünftige Java Kurse, aber ich hoffe, ich konnte darlegen, was schief läuft.

Und wenn Du gewisse Hinweise nicht verstehst (ist nichts schlimmes), zeigt doch, dass gewisse Grundlagen eben nicht behandelt wurden in dem Tutorial. Und dass wichtige Grundlagen fehlen. Daher die Empfehlung: Schau Dir z.B. das genannte Buch an! So lange Posts wie diesen sind in meinen Augen Unsinn, denn auch ich mache den Fehler, dass ich versuche komplexe Sachverhalte in viel zu kurzer Weise zu erläutern. Und das mal eben so. Dabei gibt es das alles in vernünftiger Form gut überdacht frei Verfügbar im Netz: http://openbook.rheinwerk-verlag.de/javainsel9/index.htm
Ich hoffe du verstehst nun auch unser Problem mit Deiner Fragestellung: die kurzen, knappen und prägnanten Antworten sind teilweise nicht möglich und die Ansätze haben große Verständnisprobleme.

Du musst meinen Vorschlag auch nicht wahrnehmen. Du kannst gerne auf Discord mit denen reden, die dieses Tutorial toll finden und dieses Vorgehen tatsächlich supporten wollen. Aber zumindest mein Anspruch ist dies nicht. Ich helfe gerne, aber da muss es auch etwas Sinn machen.
 
Passende Stellenanzeigen aus deiner Region:

Oben