Problem z deserializacją ArrayList

0

Hej! Stworzyłem sobie listę ArrayList w której skład jako kolejne elementy wchodzą własne klasy (zamiast np int czy string).
Wszystko fajnie się serializuje do pliku, natomiast problem jest przy deserializacji.
Jest rzucany wyjątek "java.util.ArrayList cannot be cast to ustawieniatestulibrary.UstawieniaTestu2" a przy kompilacji jest ostrzeżenie foojava uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.foo

Kod źródłowy tzn. fragment

// tutaj w osobnym pliku jar przechowuje klase ktora serializuje
// ten plik jest wspoldzielony pomiedzy 2 programy

 
// TestPytania.java

package ustawieniatestulibrary;
import java.io.*;

public class TestPytania implements Serializable {

  private static final long serialVersionUID = 1L;
  public String TrescPytania = null;
  public String Odpowiedz1Tresc = null;
  public String Odpowiedz2Tresc = null;
  public String Odpowiedz3Tresc = null;
  public String Odpowiedz4Tresc = null;
  public boolean Odpowiedz1CzyPoprawna = false;
  public boolean Odpowiedz2CzyPoprawna = false;
  public boolean Odpowiedz3CzyPoprawna = false;
  public boolean Odpowiedz4CzyPoprawna = false;
  public int IloscPunktowZaPoprawnaOdpowiedz = 0;
 // itp.
}


  
}

// modul glowny edytora w ktorym chce wczytywac i zapisywac kolekcje ArrayList z pytaniami do testu.
// kazdy element w ArrayList to osobne pytanie z odpowiedzami itp.

  
public ArrayList <ustawieniatestulibrary.TestPytania>ListaPytan = new ArrayList<ustawieniatestulibrary.TestPytania>();
    
....
// serializacja - tutaj jest ok, przynajmniej w notatniku wyglada na to ze zapisuje wszystko
    public boolean ZapiszTestDoPliku(String nazwa_pliku)
    {
                
        try
        {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(nazwa_pliku));
            out.writeObject(ListaPytan);
            out.close();
         } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(this, e.toString(), "Błąd", JOptionPane.ERROR_MESSAGE);
         } catch (IOException e) {
            JOptionPane.showMessageDialog(this, e.toString(), "Błąd", JOptionPane.ERROR_MESSAGE);
         }
        
        return true;
    }

//...

   public void OtworzPlikZTestem(String nazwa_pliku)
    {
       ArrayList <ustawieniatestulibrary.TestPytania>lista_pytan2 = new ArrayList <ustawieniatestulibrary.TestPytania>();
        try
        {     
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(nazwa_pliku));
        // tutaj ponizej cos jest nie tak :/ rzuca ten wyjatek
          lista_pytan2 = (ArrayList <ustawieniatestulibrary.TestPytania>) in.readObject();
            
            
        }
        catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(this, e.toString() + " " + nazwa_pliku, "Błąd", JOptionPane.ERROR_MESSAGE);
         } catch (IOException e) {
            JOptionPane.showMessageDialog(this, e.toString() + " " + nazwa_pliku, "Błąd", JOptionPane.ERROR_MESSAGE);
         }
           catch (ClassNotFoundException e) {
            JOptionPane.showMessageDialog(this, e.toString() + " " + nazwa_pliku, "Błąd", JOptionPane.ERROR_MESSAGE);
       }        
        
    }
 

Może niewłaściwie używam typów generycznych?
Sam nie wiem. W przypadku standardowych typów danych czy pojedynczej klasy jest ok, tylko jest problem, jak chce zrobić serializacje własnych typów danych do ArrayList
Z góry dzięki za pomoc :)

0

Ale przecież w pokazanych fragmentach nigdzie nie rzutujesz na: ustawieniatestulibrary.UstawieniaTestu2. Pokaż fragment kodu który jest odpowiedzialny za wywalenie się kodu, oraz zrekompiluj projekt z opcją -Xlint:unchecked (tak jak nakazuje komunikat), aby dowiedzieć się czemu ten komunikat się pojawia.

0

Ok, skompilowałem z tym parametrem. Kompilator wypisał mi :
warning: [unchecked] unchecked cast
lista_pytan2 = (ArrayList <ustawieniatestulibrary.TestPytania>) in.readObject();
required: ArrayList<TestPytania>
found: Object
1 warning

0

No niestety generyki w Javie są kulawe. Wymodziłem coś takiego:

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

class Rzutnik {

    @SuppressWarnings("unchecked")
    public static <T> Collection<T> rzutujKolekcję(Class<T> clazz, Object object) {
        return (Collection<T>) object;
    }
}

public class Main {

    public static void main(String[] args) {
        Object list1 = Arrays.asList(1, 2, 3);
        List<Integer> list2 = (List<Integer>) Rzutnik.rzutujKolekcję(Integer.class, list1);
        System.out.println(list2.toString());
    }
}

Jest OK dla wszelkich kolekcji. Jeśli potrzebujesz zrobić rzutowanie dla jakiejś konkretnej klasy, która nie jest kolekcją generyczną ale jest typem generycznym, to musisz zrobić następną podobną funkcję. Warningu nie ma za sprawą adnotacji dla kompilatora, generalnie używanie SuppressWarnings jest niewskazane, ale niestety czasem trzeba.

Poza tym dalej nie podałeś kodu odpowiedzialnego za rzucenie wyjątku.

0

Tzn wyjątek generuje ten kod
lista_pytan2 = (ArrayList <ustawieniatestulibrary.TestPytania>) in.readObject();

W poniedziałek jeszcze coś pokombinuje. A może spróbować na typach niegenerycznych?
Heh, w C# bez problemów serializowałem kolekcje własnych klas do Arraylist.

0

To jest niemożliwe, aby ta linia generowała ten wyjątek ponieważ treść wyjątku jest taka: "java.util.ArrayList cannot be cast to ustawieniatestulibrary.UstawieniaTestu2", a więc odnosi się do rzutowania na klasę UstawieniaTestu2. Stawiam na to, że np nie przekompilowałeś kodu po zapisaniu, albo coś w ten deseń. Zapisz wszystkie pliki źródłowe, usuń wszystkie pliki programu (także dane stworzone przez program), zbuduj od nowa i odpal.

0
Wibowit napisał(a)

To jest niemożliwe, aby ta linia generowała ten wyjątek ponieważ treść wyjątku jest taka: "java.util.ArrayList cannot be cast to ustawieniatestulibrary.UstawieniaTestu2", a więc odnosi się do rzutowania na klasę UstawieniaTestu2. Stawiam na to, że np nie przekompilowałeś kodu po zapisaniu, albo coś w ten deseń. Zapisz wszystkie pliki źródłowe, usuń wszystkie pliki programu (także dane stworzone przez program), zbuduj od nowa i odpal.

Hmmm przebuduję wszystko od nowa w poniedziałek, bo projekt mam zapisany na drugim komputerze i nie wgrywałem nigdzie na serwer czy poczte :)
A może mieć znaczenie, że klasy które serializuje to przechowuje w osobnym projekcie i pliku JAR?

0

A może mieć znaczenie, że klasy które serializuje to przechowuje w osobnym projekcie i pliku JAR?

Oczywiście, zwłaszcza jeśli na etapie kompilacji nie są sprawdzane zależności między JARkami.

0

Ok, to posprawdzam wszystko. Kurcze, wcześniej wszystko działało. Problem się pojawił jak zacząłem deserializować drugą klasę (tą z ArrayList), przy deserializacji pojedynczej klasy było ok.
Chyba środowisko programistyczne (IDE) tj. Netbeans nic nie namieszał :) Swoją drogą całkiem przyjemnie się w tym tworzy. :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1