– Cześć, Amigo! Dziś zgłębimy kolejny ciekawy temat. A dokładnie, zapisywanie i ładowanie (rekonstrukcja) obiektów. Załóżmy, że mamy klasę Cat:

Kod
class Cat
{
 public String name;
 public int age;
 public int weight;
}

I powiedzmy, że chcemy dodać wygodny mechanizm do zapisywania do pliku oraz ładowania z pliku.

Moglibyśmy zrobić to w ten sposób:

Kod
class Cat {
    public String name;
    public int age;
    public int weight;

    public void save(PrintWriter writer) throws Exception {
        writer.println(name);
        writer.println(age);
        writer.println(weight);
        writer.flush();
    }

    public void load(BufferedReader reader) throws Exception {
        name = reader.readLine();
        age = Integer.parseInt(reader.readLine());
        weight = Integer.parseInt(reader.readLine());
    }
}

– Wow! – To takie łatwe. Po prostu zapisujemy wartości każdego argumentu, po jednym w każdej linii. Kiedy ładujemy plik, odczytujemy je w tej samej kolejności. To idealne rozwiązanie.

– Dzięki, Amigo. Teraz możesz napisać metody save i load dla tej grupy klas:

Kod
class Cat
{
 public String name;
 public int age;
 public int weight;
}
class Dog
{
 public String name;
 public int age;
}
class Human
{
 public Cat cat;
 public Dog dog;
}

Masz obiekt Human, który może mieć jednego psa i jednego kota.

– Mam rozwiązanie:

Kod
class Cat {
    public String name;
    public int age;
    public int weight;

    public void save(PrintWriter writer) throws Exception {
        writer.println(name);
        writer.println(age);
        writer.println(weight);
        writer.flush();
    }

    public void load(BufferedReader reader) throws Exception {
        name = reader.readLine();
        age = Integer.parseInt(reader.readLine());
        weight = Integer.parseInt(reader.readLine());
    }
}
Kod
class Dog {
    public String name;
    public int age;

    public void save(PrintWriter writer) throws Exception {
        writer.println(name);
        writer.println(age);
        writer.flush();
    }

    public void load(BufferedReader reader) throws Exception {
        name = reader.readLine();
        age = Integer.parseInt(reader.readLine());
    }
}
Kod
public class Human {
    public Cat cat;
    public Dog dog;

    public void save(PrintWriter writer) throws Exception {
        cat.save(writer);
        dog.save(writer);
    }

    public void load(BufferedReader reader) throws Exception {
        cat.load(reader);
        dog.load(reader);
    }
}

– To bardzo dobre rozwiązanie. Ale co się dzieje, gdy Human ma psa, ale nie ma kota?

Gdzie są sprawdzane typy null?

– Już to naprawiam:

Kod
public class Human {
    public Cat cat;
    public Dog dog;

    public void save(PrintWriter writer) throws Exception {
        if (cat != null)
            cat.save(writer);
        if (dog != null)
            dog.save(writer);
    }

    public void load(BufferedReader reader) throws Exception {
        cat = new Cat();
        cat.load(reader);
        dog = new Dog();
        dog.load(reader);
    }
}

– Nadal nie jest całkiem poprawnie. Masz dwa błędy:

1) Osoba może nie mieć kota lub psa, ale i tak zostaną one utworzone, gdy metoda load zostanie wywołana

2) Jeśli zapisujemy tylko psa, jego dane zostaną odczytane przez kota po jego załadowaniu.

– A więc co powinienem zrobić?

Nie możemy pominąć zapisu zmiennych, w przeciwnym razie będziemy mieli problemy z ich odczytem. Musisz się upewnić, że zmienne, które mają wartość null podczas operacji zapisu są ustawione na null podczas operacji ładowania. Oto moja wersja:

Kod
public class Human {
    public Cat cat;
    public Dog dog;

    public void save(PrintWriter writer) throws Exception {
        String isCatPresent = cat != null ? "tak" : "nie";
        writer.println(isCatPresent);
        writer.flush();

        if (cat != null)
            cat.save(writer);

        String isDogPresent = dog != null ? "tak" : "nie";
        writer.println(isDogPresent);
        writer.flush();

        if (dog != null)
            dog.save(writer);
    }

    public void load(BufferedReader reader) throws Exception {

        String isCatPresent = reader.readLine();
        if (isCatPresent.equals("tak")) {
            cat = new Cat();
            cat.load(reader);
        }

        String isDogPresent = reader.readLine();
        if (isDogPresent.equals("tak")) {
            dog = new Dog();
            dog.load(reader);
        }
    }
}

– Tak, podoba mi się to rozwiązanie.

– Zgadza się, jest fajne.