Java Properties
- Create a Properties Instance
- Set Properties
- Get Properties
- Remove Properties
- Iterate Properties
- Store Properties to File
- Property File Format
- Load Properties From File
- Store Properties to XML File
- XML Property File Format
- Load Properties from XML File
- Load Properties From the Classpath
- ResourceBundle Properties
- Default Properties
- System Properties
- Properties is a Subclass of Hashtable - by Mistake!
Jakob Jenkov |
The Java Properties class, java.util.Properties
, is like a Java Map of
Java String key and value pairs. The Java Properties
class
can write the key, value pairs to a properties file on disk, and read the properties back in again. This is an
often used mechanism for storing simple configuration properties for Java applications.
Create a Properties Instance
To use the Java Properties
class you must first create a Properties
instance.
You do so via its constructor and the Java new
instruction. Here is an example of creating a
Java Properties
instance:
Properties properties = new Properties();
Set Properties
To set properties in a Java Properties
instance you use the setProperty()
method.
Here is an example of setting a property (key - value pair) in a Java Properties
object:
properties.setProperty("email", "john@doe.com");
This example sets the property with the key email
to the value john@doe.com
.
Get Properties
To get properties from a Java Properties
object you use the getProperty()
method,
passing the key of the property to get as parameter. Here is an example of getting a property from a
Java Properties
instance:
String email = properties.getProperty("email");
Remove Properties
You can remove a property from a Java Properties
instance using its remove()
method,
passing as parameter to remove()
the key for the property to remove. Here is an example of
removing a property from a Java Properties
instance:
properties.remove("email");
Iterate Properties
You can iterate the keys of a Java Properties
instance by obtaining the key set for the
Properties
instance, and iterating this key set. Here is an example of obtaining the key set
of a Java Properties
to iterate all its keys:
Properties properties = new Properties(); properties.setProperty("key1", "value1"); properties.setProperty("key2", "value2"); properties.setProperty("key3", "value3"); Iterator keyIterator = properties.keySet().iterator(); while(keyIterator.hasNext()){ String key = (String) keyIterator.next(); String value = properties.getProperty(key); System.out.println(key + " = " + value ); }
This example will print out the following lines:
key1 = value1 key2 = value2 key3 = value3
Store Properties to File
You can store the property key, value pairs to a properties file which can be read again later on.
You store the contents of a Properties
object via its store()
method.
Here is an example of storing the contents of a Java Properties
to a properties file:
Properties properties = new Properties(); properties.setProperty("property1", "value1"); properties.setProperty("property2", "value2"); properties.setProperty("property3", "value3"); try(FileWriter output = new FileWriter("data/props.properties")){ properties.store(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
Property File Encoding
By default the Java Properties
file encoding is ISO-8859-1 (Latin-1)
. However,
these days it is more common to use UTF-8 as encoding. You can specify the file encoding to use
as the second parameter of the Java FileWriter used when the file is
stored. Here is an example of setting the Java Properties
file encoding (charset) to UTF-8:
try(FileWriter output = new FileWriter("data/props.properties", Charset.forName("UTF-8"))){ properties.store(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
Property File Format
A Java Properties
property file consists of lines with one key=value
pair on each line.
Here is an example Java Properties
property file:
#These are properties #Thu Jul 04 21:29:20 CEST 2019 property2=value2 property1=value1 property3=value3
The lines starting the #
are comments. Notice the first line of the properties file is actually
the comment that was passed as second parameter to the store()
method call in the code example
in the previous section about storing properties to a property file.
The lines following the key=value
format contain the property key, value pairs.
Load Properties From File
You can also load properties stored in a property file back into a Java Properties
object
via its load()
method. Here is an example of loading a property file into a Java Properties
object:
Properties properties = new Properties(); try(FileReader fileReader = new FileReader("data/props.properties")){ properties.load(fileReader); } catch (IOException e) { e.printStackTrace(); }
File Encoding When Loading Properties File
By default the load()
method will assume that the loaded file is encoded using
ISO-8859-1 (Latin-1)
. If your property file is using another encoding, for instance UTF-8
,
you must specify the encoding as the second parameter to the Java FileReader
used to load the properties file. Here is an example of setting the file encoding to UTF-8
when loading a Java Properties
file:
try(FileReader fileReader = new FileReader("data/props.properties", Charset.forName("UTF-8"))){ properties.load(fileReader); } catch (IOException e) { e.printStackTrace(); }
Store Properties to XML File
The Java Properties
class can also write the key-value pairs stored in it to an XML file
via its storeToXML()
. Here is an example of storing a Java Properties
to an XML file:
Properties properties = new Properties(); properties.setProperty("property1", "value1"); properties.setProperty("property2", "value2"); properties.setProperty("property3", "value3"); try(FileOutputStream output = new FileOutputStream("data/props.xml")){ properties.storeToXML(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
Property XML File Encoding
By default the Java Properties
XML property file encoding is UTF-8.
Note, that this is the reverse default of non-XML property files.
If you need to use another encoding for the XML file, this is possible.
You can specify the file encoding to use as the third parameter to the storeToXML
method.
Here is an example of storing a Java Properties
to XML using the ISO-8859-1
encoding:
try(FileOutputStream output = new FileOutputStream("data/props.xml")){ properties.storeToXML(output, "These are properties", Charset.forName("ISO-8859-1")); } catch (IOException e) { e.printStackTrace(); }
XML Property File Format
The Java Properties
object stored to XML file in the example in the previous section
looks like this:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>These are properties</comment> <entry key="property2">value2</entry> <entry key="property1">value1</entry> <entry key="property3">value3</entry> </properties>
Notice how the comment passed to the storeToXML()
method is enclosed in a
comment
XML element, and not in an XML comment (<!-- -->
) .
Load Properties from XML File
You can load properties from an XML property file into a Java Properties
object via its
loadFromXML()
method. Here is an example of loading properties from an XML property file
into a Java Properties
object:
Properties properties = new Properties(); try(FileInputStream fileInputStream = new FileInputStream("data/props.xml")){ properties.loadFromXML(fileInputStream); } catch(IOException e){ e.printStackTrace(); }
File Encoding When Loading XML Properties Files
By default the loadFromXML()
method will assume that the XML file is stored using the
UTF-8
encoding. Note, that this is the reverse of the defaults for non-XML property files.
If your XML file is using a different encoding, e.g. ISO-8859-1 (Latin-1)
,
then your XML file must specify the encoding inside it. This is done by including the following line as the
very first line of your XML properties file:
<?xml version="1.0" encoding="ISO-8859-1"?>
Load Properties From the Classpath
It is possible to load properties into a Java Properties
from a file that is available on the
classpath. That file could thus be located inside the same JAR file as the application loading the properties,
or inside another JAR file or directory available on the Java classpath when your Java application is executed.
To load properties from a file available on the classpath you need to obtain a Class
instance
first. In the example below I obtain it from the class that contains the main()
method of my application:
Class aClass = PropertiesExample.class;
Once I have the Class
instance I can call its getResourceAsStream()
method which
returns a Java InputStream referencing the file. Here is an example
of obtaining a reference to a file from the classpath:
InputStream inputStream = aClass.getResourceAsStream("/myProperties.properties");
The file would have to be located in the root directory of the classpath. If you put it into a subdirectory,
the path passed to getResourceAsStream()
should reflect that. E.g.
/subdir/myProperties.properties
.
Using the InputStream
you can load the file into a Java Properties
instance, using
either the load()
or loadFromXML()
methods explained earlier in this
Java Properties tutorial. Which method to use depends on the format used by the property file.
Here is an example of loading the properties via load()
:
Class aClass = PropertiesExample.class; InputStream inputStream = aClass.getResourceAsStream("/myProperties.properties"); Properties fromClasspath = new Properties(); try { fromClasspath.load(inputStream); } catch (IOException e) { e.printStackTrace(); }
ResourceBundle Properties
Java contains a special type of properties called a ResourceBundle. A ResourceBundle
is a bundle
of files that together make up a bundle. Typically, each file will contain a set of properties specifically
targeted for a specific language. Thus, each file will typically contain the same set of property keys, but
with values that are specific to the language targeted by that file. ResourceBundle property files
are typically loaded from the classpath.
ResourceBundle's are a common way to internationalize your application. I have covered internationalization of
Java applications in my Java Internationalization tutorial.
The ResourceBundle
class is covered as part of that tutorial, in the
Java ResourceBundle tutorial.
Default Properties
The Java Properties
class has the ability to provide default property values for properties
that do not have any key registered in the Properties
instance. There are two ways of using default
property values. These are:
- Provide a default value to the
getProperty()
method. - Provide a
Properties
instance containing default values when creating a newProperties
instance.
The following sections will show example of both of these ways of providing default values for properties.
Default Values With getProperty()
The getProperty()
method comes in a version that takes an extra parameter which is the default
value to return in case the Properties
instance does not contain a value for the given key.
Here is an example of calling getProperty()
with a default value:
Properties properties = new Properties(); String preferredLanguage = properties.getProperty("preferredLanguage", "Danish");
If the Properties
instance does not contain a property for the key preferredLanguage
,
then the value Danish
will be returned - instead of returning null
which would have
been returned if no default value had been passed to getProperty()
.
Default Values With a Default Properties Instance
The Java Properties
class can be instantiated with another Properties
instance
containing default values to use when the newly created Properties
instance does not contain
a value for a requested property key. Here is an example of instantiating a Properties
instance with another Properties
instance for providing default values:
Properties defaultProperties = new Properties(); defaultProperties.setProperty("preferredLanguage", "Danish"); Properties newProperties = new Properties(defaultProperties); String language = newProperties.getProperty("preferredLanguage"); System.out.println("Preferred language: " + language);
Since we did not set any property value for the key preferredLanguage
in the
newProperties
instance, the newProperties
instance will look in the
defaultProperties
for a value instead.
System Properties
The System Properties in Java is a special Property
instance containing system specific properties.
These System properties are settings for the Java VM etc.
You access the Java System Properties via the System.getProperties()
method. Here is an example
of getting the Java System Properties:
Properties systemProperties = System.getProperties();
You can now get and set System specific properties via this Properties
instance.
The
System
class also has a getProperty()
and setProperty()
method
which are shortcuts to the Properties getProperty()
and setProperty()
methods
of the System Properties
instance. Here is an example of calling System.getProperty()
and System.setProperty()
:
System.setProperty("key1", "value1"); String value1 = System.getProperty("key1"); //The above is equal to: Properties systemProperties = System.getProperties(); systemProperties.setProperty("key1", "value1"); String value1 = systemProperties.getProperty("key1");
Setting Java System Properties via the Command Line
You can set Java System property keys and values when you startup your Java application, via the Java command
on the command line. You do so via the -D
argument. Here is an example of setting Java System
properties via the command line:
java -Dkey1=value -cp . com.jenkov.MyApp
This command tells Java to execute the class com.jenkov.MyApp
, using current directory as
classpath, and setting the System property named key1
to the value value1
.
System properties that are set on the command line are also available at runtime via the System Properties.
You could access the above key1
property inside your application, like this:
String key1Property = System.getProperty("key1");
Properties is a Subclass of Hashtable - by Mistake!
The Java Properties
class is a subclass of the Java Hashtable
class, and as I will show
you - this is actually a design mistake! It is a great example of when the classic "Is a / Has a" OOP rule about
when to use inheritance vs. composition fails. Let's see how.
Being a subclass of Hashtable
, you can actually use the get()
and put()
method of the Hashtable
class, which allow the use of non-string keys and values. This defeats the
purpose of the Properties
class, which is to function as a string,string map.
Here is an example of using put()
on Properties
:
Properties asProperties = new Properties(); asProperties.put(123, 456); asProperties.put("abc", 999);
Notice how it is possible to call put()
with non-string values.
Just to make it clear: You should NOT use the put()
and get()
method of the
Properties
class! Using these methods can lead to unpredictable results. Look at this example:
Properties asProperties = new Properties(); asProperties.put("abc", 999); String abc = asProperties.getProperty("abc"); System.out.println(abc);
The getProperty("abc")
call will actually return null
!!
If instead the value passed to put()
had been two strings, then it would have worked as expected.
Look at this example:
Properties asProperties = new Properties(); asProperties.put("abc", "999"); String abc = asProperties.getProperty("abc"); System.out.println(abc);
Notice how the second value passed to put()
is now also a string. Now the
getProperty("abc")
call actually returns the string 999
.
Even if you can get get()
and put()
to work, I would recommend that you do not
use these methods. Stick to setProperty()
and getProperty()
methods.
As mentioned earlier, this is an example of the "Is a / Has a" gone wrong. A Java Properties
instance clearly is as Hashtable
, but it should not share the Hashtable
interface. So - the "Is a" part of this rule should be interpreted as "Should be usable as a" instead.
Using that formulation, Properties
would not have been made a subclass of Hashtable
,
because Properties
should not be usable as a Hashtable
.
Instead, the Properties
class should have just had an internal Hashtable
to keep the
property key,value pairs in.
Tweet | |
Jakob Jenkov |