Gotcha in Java Properties


Don't mix Properties.put and getProperty
Today, I made a mistake, the code is like below: I put a key/value pair, but the getProperty return null, so the code throws NPE which I didn't expect.
// Don't mix put and getProperty
properties.put("aint", 123);
// Throws NumberFormatException, Throws NumberFormatException, as properties.getProperty("aint") return NULL.
aint = Integer.parseInt(properties.getProperty("aint"));
Why getProperty returns null?
The reason is that Properties extends Hashtable, put its value into a Hashtable. its getProperty method will only return String value, it first use call super.get(key) to search the Hashtable, if the key doesn't exist, or its value is not a String, it will try to get from the string value from defaults.
public String getProperty(String key) {
        Object oval = super.get(key);
        String sval = (oval instanceof String) ? (String)oval : null;
        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
    }
As we usually will read Properties from a configuration file, and later save it to the file, so it's better we always use getProperty and setProperty, but use put, and get methods.
defaults in Properties
defaults is also a Properties. When construct a new properties:newProp, we can pass a Properties:oldProp, it will save it as an instance value, and leave it here. When get value of a key, it will first search the Properties itself, it not found, it will search the defaults.

When you use remove to remove a key, it will only remove from the Properties's Hashtable, not from defaults. Later get(key) will return null as it only searches the Properties's Hashtable, but getProperty will return the value in the defaults.

If you don't like this behavior, you can use properties.putAll(aProperties); this will copy all element into the Hashtable of this new peoperties.
Summary
Java Properties is not well designed, as it extends Hashtable directly, and expose many mehtods of Hashtable which it should not. But it's still the simple way to read and save properties from/to a file.

Just be careful when we use it, always use getProperty and setProperty, not put nor get methods.
The test code is like below:

private static void testProperties() {
 int aint;
 // SHould always use setProperty and getProperty
 Properties properties = new Properties();
 properties.setProperty("aint", "123");
 aint = Integer.parseInt(properties.getProperty("aint"));

 // Don't mix put and getProperty
 properties = new Properties();
 properties.put("aint", 123);
 // Throws NumberFormatException, as properties.getProperty("aint") return NULL.
 try {
  aint = Integer.parseInt(properties.getProperty("aint"));
 } catch (NumberFormatException e) {
  e.printStackTrace();
 }

 Properties oldProperties = new Properties();
 oldProperties.setProperty("defaultKey", "value");
 Properties newProps = new Properties(oldProperties);
 newProps.remove("defaultKey");
 // print null
 System.out.println(newProps.get("defaultKey"));

 // print value
 System.out.println(newProps.getProperty("defaultKey"));
}

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)