CoreJava Java9

Java 9 – Immutable List of Objects Using List.of()

Java 9 – Immutable List of Objects Using List.of()

Java 9's List.of() factory method creates an unmodifiable list with a concise, one-line syntax. Earlier posts showed List.of() with primitive-wrapper and String elements. This post shows how to use it with a custom bean (POJO) — a more realistic use case for application development.

What Changes With Bean Objects?

The List.of() method works the same way regardless of the element type. The key difference is that bean objects are mutable — the list itself is immutable (you can't add or remove elements), but you can still call setters on the objects inside the list. This is an important distinction.

Product.java (Bean)

package com.java9r;

public class Product {

    private String id;
    private String name;
    private double price;

    public Product(String id, String name, double price) {
        this.id    = id;
        this.name  = name;
        this.price = price;
    }

    public String getId()    { return id; }
    public String getName()  { return name; }
    public double getPrice() { return price; }

    public void setId(String id)       { this.id = id; }
    public void setName(String name)   { this.name = name; }
    public void setPrice(double price) { this.price = price; }

    @Override
    public String toString() {
        return String.format("Product{id='%s', name='%s', price=%.1f}", id, name, price);
    }
}

ImmutableListWithBean.java

package com.java9r;

import java.util.List;

public class ImmutableListWithBean {

    public static void main(String[] args) {

        // Create an immutable list of Product objects
        List<Product> products = List.of(
            new Product("100", "Laptop",      75000.0),
            new Product("101", "Smartphone",  25000.0),
            new Product("102", "Tablet",      35000.0),
            new Product("103", "Monitor",     15000.0),
            new Product("104", "Keyboard",     2500.0)
        );

        System.out.println("Products List");
        System.out.println("=============");

        // Iterate using forEach with lambda
        products.forEach(p -> {
            System.out.println("Id:    " + p.getId());
            System.out.println("Name:  " + p.getName());
            System.out.println("Price: " + p.getPrice());
            System.out.println("-------------------------");
        });

        System.out.println("Total products: " + products.size());

        // The list is immutable — cannot add or remove
        try {
            products.add(new Product("105", "Mouse", 1500.0));
        } catch (UnsupportedOperationException e) {
            System.out.println("\nCannot add to immutable list: " + e.getClass().getSimpleName());
        }

        // But the objects inside are still mutable (if they have setters)
        products.get(0).setPrice(70000.0);
        System.out.println("Updated price: " + products.get(0).getPrice());
    }
}

Output

Products List
=============
Id:    100
Name:  Laptop
Price: 75000.0
-------------------------
Id:    101
Name:  Smartphone
Price: 25000.0
-------------------------
Id:    102
Name:  Tablet
Price: 35000.0
-------------------------
Id:    103
Name:  Monitor
Price: 15000.0
-------------------------
Id:    104
Name:  Keyboard
Price: 2500.0
-------------------------
Total products: 5

Cannot add to immutable list: UnsupportedOperationException

Updated price: 70000.0

Iterating – All Options

// 1. forEach with lambda
products.forEach(p -> System.out.println(p.getName()));

// 2. Enhanced for loop
for (Product p : products) {
    System.out.println(p.getId() + ": " + p.getName());
}

// 3. Stream API
products.stream()
        .filter(p -> p.getPrice() > 20000)
        .map(Product::getName)
        .forEach(System.out::println);

// 4. Stream with sorted
products.stream()
        .sorted((a, b) -> Double.compare(a.getPrice(), b.getPrice()))
        .forEach(System.out::println);

List.of() With Beans – Rules

Operation Allowed? Result
list.add(new Product(...)) No UnsupportedOperationException
list.remove(0) No UnsupportedOperationException
list.set(0, newProduct) No UnsupportedOperationException
list.get(0).setPrice(100) Yes Modifies the bean object (list structure unchanged)
list.forEach(...) Yes Read-only iteration works fine
list.contains(...) Yes Works (uses equals())

Truly Immutable Objects

If you want a fully immutable list (where neither the list nor its elements can be changed), make the bean itself immutable using a record (Java 16+) or by making all fields final and removing setters:

// Java 16+ record — automatically immutable
record Product(String id, String name, double price) {}

List<Product> products = List.of(
    new Product("100", "Laptop",     75000.0),
    new Product("101", "Smartphone", 25000.0)
);
// products.get(0) has no setters — fully immutable

Summary

List.of() in Java 9 creates an unmodifiable list with a clean, one-line syntax that works with any object type, including custom beans. The list structure is immutable — you cannot add, remove, or replace elements. However, if the bean objects have setters, their fields can still be changed. To achieve full immutability, combine List.of() with immutable bean objects (using Java records or final-field-only classes). This pattern is ideal for read-only datasets like product catalogs, configuration tables, and test fixtures.

Topics: CoreJava Java9
← Newer Post Older Post →

Comments

https://www.blogger.com/comment/frame/6690124484600543990?po=2909413786574550497&hl=en&saa=85391&origin=https://www.java9r.com