Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8157123

java.util.Properties class is violating the Liskov's Substitution Principle (LSP)

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_65"
      Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 Professional 64 bit

      A DESCRIPTION OF THE PROBLEM :
      The next example is how java.util.Properties extends java.util.Hashtable, which is wrong (a property file is not a hashtable).

      Because inherits from , the and methods can be applied to a object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not . The method should be used instead. If the or method is called on a "compromised" Properties object that contains a non- key or value, the call will fail. Similarly, the call to the or method will fail if it is called on a "compromised" Properties object that contains a non- key.

      ****Here is the programming example1 :****
      Properties extnNos = new Properties();
      extnNos.put("Kathy", "3542");
      extnNos.put("Joel", "4433");
      // mistake in the following statement; 3224 instead of "3224"
      extnNos.put("Joshua", 3224);
      extnNos.list(System.out);

      When executed, this program crashes:

      -- listing properties --
      Kathy=3542
      Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
      at java.util.Properties.list(Properties.java:1050)
      at UseProperties.main(UseProperties.java:10)


      ****Here is the programming example2 :****
      Properties properties = new Properties();
      properties.put("LOGNAME", "gsamarthyam");
      System.out.println("LOGNAME=" + properties.getProperty("LOGNAME"));
      Properties propertiesCopy = new Properties(properties);
      System.out.println("LOGNAME=" + propertiesCopy.get("LOGNAME"));

      This program prints:

      LOGNAME=gsamarthyam
      LOGNAME=null

      The output is clearly wrong. The get() method comes from the base class Hashtable and it isn't overridden in the derived class Properties. However, if we call the getProperty method, then the code works (see http://www.docjar.com/html/api/java/util/Properties.java.html).

      When we create a copy of a Properties file with the call new Properties(properties), the reference to original Properties is maintained in a "defaults" variable. When looking for a key by calling getProperty, this defaults.getProperty(key) is called when the super.get(key) returns null.

      The behaviour exhibited by Properties.java is clearly wrong/misleading. It is a much more deeper problem that can be root caused to the effects of violating LSP.

      REGRESSION. Last worked in version 8u92

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the following programe:

      Properties properties = new Properties();
      properties.put("LOGNAME", "gsamarthyam");
      System.out.println("LOGNAME=" + properties.getProperty("LOGNAME"));
      Properties propertiesCopy = new Properties(properties);
      System.out.println("LOGNAME=" + propertiesCopy.get("LOGNAME"));


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      LOGNAME=gsamarthyam
      LOGNAME=null
      ACTUAL -
      Not 100% sure about the actual result, please read description for more details
      LOGNAME=gsamarthyam
      LOGNAME=null

      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
      Use HashTable class as composition inside Properties class rather extending it.

            smarks Stuart Marks
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: