2012-04-04 6 views
2

Betrachten Sie die folgende Erklärung als Teil SomeClassVariable Initialisierung Vergangenheit Xstream

private Set<String> blah = new HashSet<String>(); 

in einer Klasse hergestellt, die später ist

XStream xstream = new XStream(new JettisonMappedXmlDriver()); 
xstream.setMode(XStream.NO_REFERENCES); 

StringBuilder json = new StringBuilder(xstream.toXML(SomeClass)); 

rd = (SomeClass) xstream.fromXML(json.toString()); 

Wenn ich @Test

assertTrue(rd.getBlah().size() == 0); 

ich eine bekommen NPE auf rd.getBlah()

Wenn ich statt Initialisierung vorne, Ort der Initialisierung auf einen Konstruktor SomeClass

public SomeClass() { 
    blah = new HashSet<String>(); 
} 

Das gleiche Problem - NPE auf rd.getBlah()

Wenn ich die Getter ändern zuerst für null zu überprüfen, es funktioniert aber ..

public Set<String> getBlah() { 
    if (blah == null) 
     return new HashSet<Sgring>(); 
    return blah; 
} 

ich bin verwirrt ... Warum initialisieren nicht XStream nicht Variablen und ob faule Instanziierung notwendig ist?

+0

Ich bin ein wenig verwirrt durch xstream.toXML (Someclass); Sollte es nicht xstream.toXML (Objekt) sein, wo das Objekt vom Typ SomeClass ist? – Max

+0

Wenn es etwas gibt, wissen wir, dass 'SomeClass' ganz sicher vom' SomeClass' ist :) – JAM

+0

Mein Punkt war: Nehmen Sie, was Sie oben auf Nennwert geschrieben haben, wenn SomeClass ein Typ ist, dann Ihr Code oben tut nicht kompilieren. SomeClass ist nicht vom Typ SomeClass und auch SomeClass.class vom Typ SomeClass ... – Max

Antwort

4

XStream verwendet denselben Mechanismus wie die JDK-Serialisierung. Wenn der erweiterte Modus mit der optimierten Reflektions-API verwendet wird, wird der Standardkonstruktor nicht aufgerufen. Die Lösung ist die readResolve Verfahren zu implementieren, wie unten:

public class SomeClass{ 
    private Set<String> blah; 

    public SomeClass(){ 
     // do stuff 
    } 

    public Set<String> getBlah(){ 
     return blah; 
    } 

    private Object readResolve() { 
     if(blah == null){ 
      blah = new HashSet<String>(); 
     } 
     return this; 
    } 
} 

Reference

+0

Danke. In der Tat funktioniert das! Zwei Dinge: Könnten Sie einen Verweis auf das oben genannte geben und wie kann ich herausfinden, ob ich im erweiterten Modus laufe oder nicht? – JAM

+0

@JAM, 1) Ich habe die Referenz unter dem Code-Snippet und 2) Ich bin mir nicht sicher, aber ich glaube, es läuft standardmäßig in diesem Modus .. – mre

+0

Warum funktioniert readObject() in diesem Fall nicht? Ich habe ein ähnliches Problem hier: http://stackoverflow.com/questions/15752945/xstream-wont-call-readobject, in dem readObject() scheint die richtige Lösung zu sein, aber nur readResolve() funktioniert. – eipark