I'm fairly new to the concept of immutable classes. Consider this class:
public class ConnectionMonitor implements MessageConsumer {
private final MonitorObject monitorObject;
private boolean isConnected = true;
private final static Logger logger = LogManager.getLogger(ConnectionMonitor.class);
public ConnectionMonitor(final MonitorObject monitorObject) {
this.monitorObject = monitorObject;
}
public boolean isConnected() {
return isConnected;
}
public void waitForReconnect() {
logger.info("Waiting for connection to be reestablished...");
synchronized (monitorObject) {
enterWaitLoop();
}
}
private void enterWaitLoop() {
while (!isConnected()) {
try {
monitorObject.wait();
} catch (final InterruptedException e) {
logger.error("Exception occured while waiting for reconnect! Message: " + e.getMessage());
}
}
}
private void notifyOnConnect() {
synchronized (monitorObject) {
monitorObject.notifyAll();
}
}
@Override
public void onMessage(final IMessage message) {
if (message.getType() == IMessage.Type.CONNECTION_STATUS) {
final String content = message.getContent();
logger.info("CONNECTION_STATUS message received. Content: " + content);
processConnectionMessageContent(content);
}
}
private void processConnectionMessageContent(final String messageContent) {
if (messageContent.contains("Disconnected")) {
logger.warn("Disconnected message received!");
isConnected = false;
} else if (messageContent.contains("Connected")) {
logger.info("Connected message received.");
isConnected = true;
notifyOnConnect();
}
}
}
I'm trying to understand how this class could be changed to an immutable one.
In particular, I don't see how the boolean field isConnected
could be made final, since it represents the connection state.
All clients of ConnectionMonitor
should just query
isConnected()
to get the connection state.
I'm aware that locking changes to isConnected
is possible or using an atomic boolean.
But I don't see how to rewrite this to an immutable class.
In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.
String is an example of an immutable type. A String object always represents the same string. StringBuilder is an example of a mutable type. It has methods to delete parts of the string, insert or replace characters, etc.
The state is mutable in react components. To make the React applications interactive we almost use state in every react component. State is initialized with some value and based on user interaction with the application we update the state of the component at some point of time using the setState method.
The only real disadvantage of immutable classes is that they require a separate object for each distinct value. Creating these objects can be costly, especially if they are large.
The ideal is to minimize mutability -- not eliminate it.
Immutable objects have multiple advantages. They're simple, thread-safe and may be shared freely.
However, sometimes we need mutability.
In "Effective Java," Joshua Bloch suggests these guidelines:
- Classes should be immutable unless there's a very good reason to make them mutable.
- If a class cannot be made immutable, limit its mutability as much as possible.
In your example, there's a very good reason for instances of the class to be mutable. But you can also see the second guideline in play: the field monitorObject
is marked final.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With