Problem z deserializacją ArrayList

Problem z deserializacją ArrayList
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 4 lata
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

Kopiuj
 
// 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.

Kopiuj
  
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 :)

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:dzień
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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 4 lata
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

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:dzień
0

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

Kopiuj
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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 4 lata
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.

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:dzień
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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 4 lata
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?

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:dzień
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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 4 lata
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. :)

LO
No dobra, przebudowałem wszystko, a wyjątek był dlatego, że funkcją przeznaczoną do odczytu ustawień testu wczytywałem plik z testem. Czeski błąd. Niby jest ok, ale nadal jest to ostrzeżenie.... Jeszcze wszystko posprawdzam dokładniej...
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)