0

How does XMLEncoder know that a property was set in the object's constructor, and thus avoid outputting it ?

Here is a simple example (run on Java 1.8) which demonstrates this: First define a simple object with getters and setters and a default constructor:

public class Simple {
 int m;
 int n;

 public int getM() { return m;}
 public void setM(int m) {this.m = m;}
 public int getN() {return n;}
 public void setN(int n) {this.n = n;   }

 public String toString() {
    return "m=" + m + ",n=" + n;
 }  

 public Simple() {
    this.m = 1;
    this.n = 2;
 }      
}

Now the main, which instantiates the object, uses a setter on one of the properties, and invokes XMLEncoder on the final object. To be sure I also print the object's properties before invoking the encoder:

public class Main {

 public static void main(String[] args) {
    Simple simple = new Simple();

    simple.setN(7);
    System.out.println(simple.toString());

    XMLEncoder encoder=null;
    try{
        encoder=new XMLEncoder(new BufferedOutputStream(
                        new FileOutputStream("simple.xml")));
    }catch(FileNotFoundException fileNotFound){
        System.out.println("ERROR: While Creating the File ");
    }
    encoder.writeObject(simple);
    encoder.close();
  }
 }

Running the program, I get the expected output: m=1,n=7 However, when I look at the file generated, I get:

<?xml version="1.0" encoding="UTF-8"?>
 <java version="1.8.0_112" class="java.beans.XMLDecoder">
 <object class="simple.Simple">
  <void property="n">
   <int>7</int>
  </void>
 </object>
</java>

Here we see that the only one property is output by XMLEncoder, whereas the previous printout of the object shows that both properties have their values set. It is as though XMLEncoder has a crystal ball and knows what happened in the past!

1 Answers1

0

It actually looks the opposite, as if it has amnesia, it could have output both n and m but it did only print one property, the one that was affected by your setter.

But Official doc says

Structurally compact: The XMLEncoder class uses a redundancy elimination algorithm internally so that the default values of a Bean's properties are not written to the stream.

So it explains its selective nature

Oleg Bogdanov
  • 1,712
  • 13
  • 19
  • Ah-ha! This make sense, i.e. when I decode the file using XMLDecoder, the instantiation of the object would initialize the properties in the constructor and the only overwrite those set outside. – Malcolm Kavalsky Dec 31 '16 at 05:06
  • yes, exactly. Nice optimization, just not very obvious – Oleg Bogdanov Dec 31 '16 at 05:08
  • After some more thought, I see a problem with this behaviour. If I use XMLEncoder to store a file with certain properties, then change the default values in the objects constructor, and run XMLDecoder on the original file, I will have different values in the object than in the previous run. Not sure about this. – Malcolm Kavalsky Jan 02 '17 at 13:09
  • Well it's common issue, if you change representation of the data you should not deserialize old saves, use versions to discard previous forms – Oleg Bogdanov Jan 02 '17 at 16:35