Are Value Classes allowed to exhibit change?

3 min read 01-09-2024
Are Value Classes allowed to exhibit change?


Are Value Classes Allowed to Exhibit Change?

Java's value classes, introduced in Java 14, are designed to represent immutable entities. While the documentation states they are final and immutable, the question arises: What happens when a value class contains a reference to a mutable object?

This article delves into this scenario and explores whether such a situation is an improper use of value classes. We'll examine relevant Java documentation, Stack Overflow discussions, and provide practical examples to clarify the matter.

Understanding Value Classes and Mutability

Let's start by reviewing the core principles of value classes. They are designed to:

  • Represent immutable data: Once a value class instance is created, its state remains constant.
  • Enhance performance: Value classes optimize memory usage and reduce object creation overhead compared to traditional classes.
  • Simplify code: Their immutability promotes thread safety and simplifies reasoning about program behavior.

Now, let's consider the question of mutability. The Java documentation, as quoted in the initial question, states that value classes are immutable, despite potentially holding references to mutable objects. This means that the value class itself cannot be modified but the mutable objects it references can be changed.

The "Observability" Debate

The crux of the matter lies in the way changes to the referenced mutable object are "observed." Consider the example provided:

value class Foo {
    Bar bar; // Bar is a mutable type
}

public int number() {
    return bar.number(); // may return different results!
}

Here, Foo holds a reference to a Bar object, which is mutable. While Foo itself remains immutable, changes to Bar can be observed through the number() method.

This scenario raises the question: Does this "observability" of changes violate the immutability principle of value classes?

The Java documentation doesn't explicitly address this. However, a Stack Overflow discussion[1] sheds light on the matter:

"The value class itself remains immutable. The mutable object held by the value class can be changed, but this does not violate the immutability of the value class."

This interpretation emphasizes that the value class itself does not change. Changes to the referenced mutable object do not affect the identity or behavior of the value class itself.

Real-World Example

Imagine a value class Coordinate representing a point in space:

value class Coordinate {
    final int x;
    final int y;
}

We can use this class to represent points in a map or a game. Now, let's say we want to add a property called color to our Coordinate class, which can change over time.

We could introduce a Color class:

class Color {
    String name;

    Color(String name) {
        this.name = name;
    }

    void changeColor(String newColor) {
        this.name = newColor;
    }
}

And modify our Coordinate class:

value class Coordinate {
    final int x;
    final int y;
    Color color;

    Coordinate(int x, int y, Color color) {
        this.x = x;
        this.y = y;
        this.color = color;
    }

    void changeColor(String newColor) {
        color.changeColor(newColor);
    }
}

In this case, Coordinate remains immutable, but the color property can be changed via the changeColor() method. The value class itself doesn't change, but its behavior can be influenced by the mutable Color object.

Conclusion

The immutability of value classes refers to their own internal state. While they can hold references to mutable objects, changes to those objects do not alter the identity or behavior of the value class itself. Therefore, it is not considered improper for a value class to contain references to mutable objects.

However, it's crucial to be mindful of the implications. While value classes remain immutable, the behavior of your code can be affected by changes to the mutable objects they reference. You should document these dependencies clearly and ensure that changes to mutable objects do not violate the intended functionality of the value class.


  1. Stack Overflow: Value class with mutable member ↩︎