Skip to content
Java collections 6 min read

Properties Class

The Properties class is Java’s built-in solution for managing key-value configuration data — think database URLs, API endpoints, or application settings stored in a simple .properties file. It extends Hashtable<Object, Object> and adds convenient methods for loading from and saving to streams, making it the standard way to externalize configuration in Java applications.

What is the Properties Class?

Properties lives in the java.util package. Every key and value is a String, even though it technically inherits from Hashtable<Object, Object>. This string-only convention is what makes .properties files so portable and easy to edit without touching code.

A typical .properties file looks like this:

# app.properties
db.url=jdbc:mysql://localhost:3306/mydb
db.user=admin
db.password=secret
app.name=MyApp
app.version=2.0

Lines starting with # or ! are comments. Keys and values are separated by = or :.

Creating a Properties Object

You can create a Properties object with or without default values:

import java.util.Properties;

public class CreateProperties {
    public static void main(String[] args) {
        // Empty properties
        Properties props = new Properties();

        // Set values manually
        props.setProperty("app.name", "DevCraftly");
        props.setProperty("app.version", "1.0");

        // Retrieve a value
        String name = props.getProperty("app.name");
        System.out.println("App: " + name);

        // Retrieve with a fallback default
        String env = props.getProperty("app.env", "production");
        System.out.println("Env: " + env);
    }
}

Output:

App: DevCraftly
Env: production

Tip: Always use getProperty(key, defaultValue) when a missing key should fall back gracefully instead of returning null.

Loading Properties from a File

The most common use case is reading a .properties file from your classpath or filesystem.

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class LoadProperties {
    public static void main(String[] args) throws IOException {
        Properties props = new Properties();

        try (FileInputStream fis = new FileInputStream("app.properties")) {
            props.load(fis);
        }

        System.out.println("DB URL : " + props.getProperty("db.url"));
        System.out.println("DB User: " + props.getProperty("db.user"));
    }
}

Output:

DB URL : jdbc:mysql://localhost:3306/mydb
DB User: admin

Tip: In a Maven/Gradle project, place app.properties inside src/main/resources. Load it from the classpath using getClass().getResourceAsStream("/app.properties") so it works in JAR files too.

Loading from the Classpath

import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;

public class ClasspathProperties {
    public static void main(String[] args) throws IOException {
        Properties props = new Properties();

        try (InputStream is = ClasspathProperties.class
                .getResourceAsStream("/app.properties")) {
            if (is == null) {
                throw new IOException("app.properties not found on classpath");
            }
            props.load(is);
        }

        System.out.println(props.getProperty("app.name"));
    }
}

Saving Properties to a File

You can persist a Properties object back to disk using store():

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class SaveProperties {
    public static void main(String[] args) throws IOException {
        Properties props = new Properties();
        props.setProperty("theme", "dark");
        props.setProperty("language", "en");

        try (FileOutputStream fos = new FileOutputStream("user.properties")) {
            props.store(fos, "User Preferences");
        }

        System.out.println("Saved successfully.");
    }
}

This writes a file like:

#User Preferences
#Fri Jun 13 10:00:00 UTC 2026
theme=dark
language=en

Note: The order of keys in the saved file is not guaranteed because Properties inherits the unordered nature of Hashtable. If you need sorted output, iterate over a TreeSet of the property names.

XML Format

Properties also supports XML via loadFromXML() and storeToXML():

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class XmlProperties {
    public static void main(String[] args) throws IOException {
        Properties props = new Properties();

        try (FileInputStream fis = new FileInputStream("config.xml")) {
            props.loadFromXML(fis);
        }

        props.forEach((k, v) -> System.out.println(k + " = " + v));
    }
}

The XML format looks like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <entry key="db.url">jdbc:mysql://localhost/mydb</entry>
    <entry key="db.user">admin</entry>
</properties>

Iterating Over All Properties

You have a few options to loop through all entries:

import java.util.Properties;

public class IterateProperties {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty("host", "localhost");
        props.setProperty("port", "8080");
        props.setProperty("debug", "true");

        // Option 1: stringPropertyNames() — only String keys
        for (String key : props.stringPropertyNames()) {
            System.out.println(key + " = " + props.getProperty(key));
        }

        // Option 2: forEach (lambda)
        System.out.println("--- forEach ---");
        props.forEach((k, v) -> System.out.println(k + " -> " + v));
    }
}

Output:

host = localhost
port = 8080
debug = true
--- forEach ---
host -> localhost
port -> 8080
debug -> true

Tip: Prefer stringPropertyNames() over keySet() when you only care about String keys — it filters out any non-string keys that may have been added through the inherited Hashtable API.

System Properties

Java exposes all JVM and OS-level settings through System.getProperties(), which returns a Properties object:

public class SystemProps {
    public static void main(String[] args) {
        // Read a single system property
        String javaVersion = System.getProperty("java.version");
        String os = System.getProperty("os.name");
        String userHome = System.getProperty("user.home");

        System.out.println("Java version : " + javaVersion);
        System.out.println("OS           : " + os);
        System.out.println("Home dir     : " + userHome);

        // Set a custom system property at runtime
        System.setProperty("app.mode", "debug");
        System.out.println("Mode: " + System.getProperty("app.mode"));
    }
}

Output:

Java version : 21.0.3
OS           : Linux
Home dir     : /home/user
Mode         : debug

Common system properties you’ll encounter:

PropertyMeaning
java.versionJDK version string
java.homeJRE installation directory
os.nameOperating system name
user.homeCurrent user’s home directory
user.dirCurrent working directory
file.separator/ on Unix, \ on Windows
line.separatorPlatform-specific line ending
path.separator: on Unix, ; on Windows

Default Properties (Fallback Chain)

You can chain Properties objects so that a lookup falls back to a parent set of defaults:

import java.util.Properties;

public class DefaultProperties {
    public static void main(String[] args) {
        // Base defaults
        Properties defaults = new Properties();
        defaults.setProperty("timeout", "30");
        defaults.setProperty("retries", "3");
        defaults.setProperty("log.level", "INFO");

        // App-specific overrides
        Properties appProps = new Properties(defaults);
        appProps.setProperty("log.level", "DEBUG"); // overrides default

        System.out.println(appProps.getProperty("timeout"));   // from defaults
        System.out.println(appProps.getProperty("retries"));   // from defaults
        System.out.println(appProps.getProperty("log.level")); // overridden
    }
}

Output:

30
3
DEBUG

This fallback chain is useful when you have environment-specific overrides on top of a shared base configuration.

Under the Hood

Properties extends Hashtable<Object, Object>, which is a legacy synchronized hash table (similar to HashMap but thread-safe). Here is what that means in practice:

  • Thread safety — all Properties methods are synchronized, so multiple threads can read and write safely. However, this synchronization also makes it slower than HashMap for single-threaded use.
  • String convention — the class was designed before Java generics. The Object, Object type parameters are historical baggage. The dedicated getProperty() / setProperty() methods enforce String types, and you should always use those instead of the raw put() / get() from Hashtable.
  • Load encodingload(InputStream) reads bytes as ISO-8859-1 (Latin-1) by default. To handle UTF-8 characters correctly, use load(Reader) with an InputStreamReader specifying StandardCharsets.UTF_8. Java 9+ changed the default encoding for property files to UTF-8 when using the module system.
  • list() vs store()list(PrintStream) is a debugging utility that truncates long values. Use store() when you actually need to persist properties.

Warning: Avoid calling the inherited put() method with non-String keys or values. It will compile fine (since Hashtable<Object, Object> accepts anything), but it will break getProperty(), which only looks up String keys. Stick to setProperty() / getProperty() exclusively.

Key Methods at a Glance

MethodDescription
setProperty(key, value)Store a string key-value pair
getProperty(key)Retrieve value or null
getProperty(key, default)Retrieve value with fallback
load(InputStream)Load from a byte stream (ISO-8859-1)
load(Reader)Load from a character stream (UTF-8 friendly)
store(OutputStream, comment)Save to a byte stream
storeToXML(OutputStream, comment)Save in XML format
loadFromXML(InputStream)Load from XML format
stringPropertyNames()Set of all String keys
list(PrintStream)Print all entries (for debugging)
  • HashMap — the modern, non-synchronized alternative to the Hashtable backing Properties
  • Collections Utility Class — utility methods that work across the collections framework
  • File Handling — reading and writing files, which you use when loading .properties files
  • Serialization — another way to persist object state beyond plain text config
  • JDBC Steps — a real-world use of Properties to supply database credentials
  • Hashtable — the parent class of Properties and its thread-safety trade-offs
Last updated June 13, 2026
Was this helpful?