Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added example code from SER08 to this rule.

...

The Employee class can now be safely used as a key for the map in the client code.

Noncompliant Code Example

Many programmers are surprised by an instance of hashcode mutability that arises due to serialization. The contract for the hashCode() method lacks any requirement that hashcodes remain consistent across different executions of an application. Similarly, when an object is serialized and subsequently deserialized, its hashcode after deserialization may be inconsistent with its original hashcode.

Wiki Markup
This noncompliant code example uses the {{Key}} class as the key index for the {{Hashtable}}. According to the Java API \[[API 2006|AA. Bibliography#API 06]\] class {{Hashtable}} documentation

To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.

This noncompliant code example follows the above advice, but can nevertheless fail after serialization and deserialization. Consequently, it may be impossible to retrieve the value of the object after deserialization by using the original key.

Code Block
bgColor#FFcccc

class Key implements Serializable {
  // Overrides hashcode and equals methods
}

class HashSer {
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Hashtable<Key,String> ht = new Hashtable<Key, String>();
    Key key = new Key();
    ht.put(key, "Value");
    System.out.println("Entry: " + ht.get(key)); // Retrieve using the key, works
	 
    // Serialize the Hashtable object
    FileOutputStream fos = new FileOutputStream("hashdata.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(ht);
    oos.close();
	 
    // Deserialize the Hashtable object
    FileInputStream fis = new FileInputStream("hashdata.ser");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Hashtable<Key, String> ht_in = (Hashtable<Key, String>)(ois.readObject());
    ois.close();
	 
    if(ht_in.contains("Value")) // Check whether the object actually exists in the Hashtable
      System.out.println("Value was found in deserialized object.");
	 
    if (ht_in.get(key) == null) // Gets printed
      System.out.println("Object was not found when retrieved using the key.");	 
  }
}

Compliant Solution

This compliant solution changes the type of the key value to be an Integer object. Consequently, key values remain consistent across multiple runs of the program, across serialization and deserialization, and also across multiple JVMs.

Code Block
bgColor#ccccff

class HashSer {
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Hashtable<Integer, String> ht = new Hashtable<Integer, String>();
    ht.put(new Integer(1), "Value");
    System.out.println("Entry: " + ht.get(1)); // Retrieve using the key
	 
    // Serialize the Hashtable object
    FileOutputStream fos = new FileOutputStream("hashdata.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(ht);
    oos.close();
	 
    // Deserialize the Hashtable object
    FileInputStream fis = new FileInputStream("hashdata.ser");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Hashtable<Integer, String> ht_in = (Hashtable<Integer, String>)(ois.readObject());
    ois.close();
	 
    if(ht_in.contains("Value")) // Check whether the object actually exists in the Hashtable
      System.out.println("Value was found in deserialized object.");
	 
    if (ht_in.get(1) == null)  // Not printed
      System.out.println("Object was not found when retrieved using the key.");	 
  }
}

This problem can also be avoided by overriding the equals() and the hashcode() method in the Key class, though it is best to avoid serializing hash tables that are known to use implementation defined parameters.

Risk Assessment

Failure to ensure that the keys used in a comparison operation are immutable can lead to non-deterministic behavior.

...