+ All Categories
Home > Education > Immutables in Java

Immutables in Java

Date post: 15-Jan-2017
Category:
Upload: marcus-biel
View: 539 times
Download: 0 times
Share this document with a friend
143
www.marcus-biel.com MARCUS BIEL, Software Craftsman Immutables in Java
Transcript
Page 1: Immutables in Java

www.marcus-biel.com

MARCUS BIEL,Software CraftsmanImmutables in Java

Page 2: Immutables in Java

The concept of Immutability has always been very important

across all programming languages.

MARCUS BIEL,Software CraftsmanImmutables in Java

Page 3: Immutables in Java

MARCUS BIEL,Software CraftsmanImmutables in Java

For a Java developer however, Immutable classes, or simply, "Immutables",

Page 4: Immutables in Java

MARCUS BIEL,Software CraftsmanImmutables in Java

have become more important than ever with the release of Java 8.

Page 5: Immutables in Java

MARCUS BIEL,Software CraftsmanImmutables in Java

Among many other cool things, this version introduced the concept of

functional programming as well as the new java.time api.

Page 6: Immutables in Java

MARCUS BIEL,Software CraftsmanImmutables in Java

Immutable classes play a key role in both of these new features.

Page 7: Immutables in Java

MARCUS BIEL,Software CraftsmanImmutables in Java

Because of this, I’ve decided to provide you with

a detailed look at Immutables.

Page 8: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Outline

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

I'll tell you exactly what an Immutable is,

Page 9: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Outline

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

its advantages and disadvantages,

Page 10: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Outline

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

and how to create an Immutable.

Page 11: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Outline

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

I’ll finish by giving you concrete advice on when to use Immutables in your daily work.

Page 12: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

So let’s start with the most important question – what is an Immutable class?

Page 13: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

In short, an Immutable class is a class whose instances

cannot be modified.

Page 14: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

The information contained in each immutable object is provided when it is created -

Page 15: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

and is frozen for its lifetime. Once an Immutable object has been created,

it is read only, forever fixed, like a fossil.

Page 16: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

USS Enterprise (NCC-1701)

ImmutableSpaceship enterprise = new ImmutableSpaceship("Enterprise");enterprise.exploreGalaxy();

So if an object is immutable, how can we modify it?

Page 17: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

What is an Immutable?

USS Enterprise (NCC-1701)

ImmutableSpaceship enterprise = new ImmutableSpaceship("Enterprise");enterprise.exploreGalaxy();

How can we change this unchangeable spaceship? How can we explore strange new worlds and “boldly go where no man has gone before”?

Page 18: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }

public final class ImmutableSpaceship { private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

What is an Immutable?

As it turns out, we can’t. As I've said, you cannot change an Immutable.

Instead, you can return a new Object that does reflect the change.

Page 19: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }

public final class ImmutableSpaceship { private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

What is an Immutable?

In this case we’d return a new ImmutableSpaceship object with

a new Destination value of “OUTER_SPACE”.

Page 20: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Outline

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

So far this seems useless. Why should you bother with Immutables?

What kind of advantages will they bring you?

Page 21: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Advantages of Immutables

• Are stable & fault tolerant

First of all, Immutable classes greatly reduce the effort needed to implement a stable

and fault tolerant system.

Page 22: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Advantages of Immutables

• Are stable & fault tolerant

After object creation, Immutables can be in only one state, which seems very confining at first,

but it’s actually extremely beneficial. Let’s see why.

Page 23: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

Imagine we have to implement a bank's accounting software.

Page 24: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

As a result of the financial crisis, the bank doesn't want its customers to be in debt.

Page 25: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

In other words, there is a business rule that

an account balance must never be negative. Such a rule is called an invariant.

Page 26: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

private void validate(long balance) { if (balance < 0) { throw new IllegalArgumentException("balance must not be negative:"+ balance); }}

To implement this rule, we will add a validation method that gets called

whenever the balance is changed.

Page 27: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

private void validate(long balance) { if (balance < 0) { throw new IllegalArgumentException("balance must not be negative:"+ balance); }}

Immutables are stable & fault tolerant

In case of an attempt to overdraw the account,

Page 28: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

private void validate(long balance) { if (balance < 0) { throw new IllegalArgumentException("balance must not be negative:"+ balance); }}

an IllegalArgumentException will be thrown.

Page 29: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

As you probably can imagine, the bank wants us to implement

a variety of functions for their clients,

Page 30: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

for example withdraw(), payDebt() and

transferMoney().

Page 31: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]} To enforce the rule that the account’s

balance must never be negative, we have to call the validation method from all these

methods.

Page 32: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]}

This seems like a lot of duplicated code. There must be a better way!

Page 33: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]} Pause here and think of an

alternative way to make sure that none of these methods would overdraw the account’s balance.

Page 34: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]}

Okay, the truth is, I tricked you a bit. We don't actually need to validate the balance in each

method.

Page 35: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]}

I said we need to validate the object whenever it is changing,

but an Immutable is not changing.

Page 36: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]}

Immutables are stable & fault tolerant

Instead, we validate the balance once in the constructor, so that no invalid object can be constructed.

Page 37: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]} Once validated,

an immutable object will stay valid for its entire lifetime.

Page 38: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]} WOW! This is really cool!

Methods like withdraw(), payDebt() and transferMoney() will return a new object, which will again call the constructor and validate the new balance.

Page 39: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) {…}

public ImmutableAccount payDebt(long amount) {…}

public ImmutableAccount transferMoney(long amount) {…}

[…]}

Immutables are stable & fault tolerant

But wait, it gets even better! An Immutable remains consistent – even in the case of an exception.

Let me give you an example:

Page 40: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

Imagine you go to the ATM -

Page 41: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

- to get some cash.

Page 42: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

You put in your bank card, you type in your PIN.

Page 43: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

Balance:

+20,000.00

The bank takes the money …

Page 44: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

0.00Balance:

Immutables are stable & fault tolerant

out of your account. But just before it gets into your hands,

Page 45: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

there’s an issue with the ATM. The money has already been taken out of your bank

account, but it isn’t coming out of the machine.

Page 46: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

0.00Balance: So now, you can kiss your money good bye.

Page 47: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

0.00Balance:

Unless the account has been implemented as an Immutable.

Page 48: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

Balance:

+20,000.00

In this case, your balance will be in the same state that it was before the failure occurred. Let’s see what this looks like in code.

Page 49: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { }[…]}

Immutables are stable & fault tolerant

If we are trying to withdraw money from our ImmutableAccount class,

Page 50: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables are stable & fault tolerant

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

and an exception occurs,

Page 51: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

Immutables are stable & fault tolerant

a new ImmutableAccount object will never be created and

the original bank account object will stay unchanged and be saved.

Page 52: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

Immutables are stable & fault tolerant

So as I’ve shown you, an Immutable object can never get into an inconsistent

state, even in the case of an exception.

Page 53: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

Immutables are stable & fault tolerant

This stability comes at no cost, apart from the cost of the initial validation.

Page 54: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

Immutables are stable & fault tolerant

It's based on the simple fact that an Immutable cannot change after object creation.

Page 55: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableAccount {

private final long balance;

public ImmutableAccount(long balance) { validate(balance); this.balance = balance; }

public ImmutableAccount withdraw(long amount) { long newBalance = newBalance(amount); return new ImmutableAccount(newBalance); }

private long newBalance(long amount) { // exception during balance calculation

}[…]}

Immutables are stable & fault tolerant

Ok, I hope you haven't fallen asleep yet. There is so much more that Immutables have to offer,

so let’s go on.

Page 56: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

• Are stable & fault tolerant• Can be shared freely

Since Immutables don’t change, they can be shared freely. Let’s see what this means.

Page 57: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

Balance

AccountAccount

Holder HolderBalance

In this example, two Mutable Account objects are

sharing the same Balance attribute.

Page 58: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

AccountAccount

Holder HolderBalance

If the Account object on the right

Page 59: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

AccountAccount

Holder HolderBalance

changes the balance, this will also indirectly influence the Account object on

the left.

Page 60: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

AccountAccount

Holder HolderBalance

If, however, the balance attribute is immutable,

Page 61: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Holder

Account

Immutables can be shared freely

Account

HolderBalanceBalance

when the Account object on the right tries to change the balance object, it will not change,

Page 62: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Account

Balance Holder

Immutables can be shared freely

Account

Holder Balance

but return a new object instead. So there will be a second balance object now.

Page 63: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Account

Balance Holder

Immutables can be shared freely

Account

Holder Balance

For the same reason - an Immutable does not need a copy constructor when copying an object.

Page 64: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

If you don’t understand what this means or you’d like to learn more about cloning and copy constructors,

check out my video “Shallow versus Deep Copy”.

http://www.marcus-biel.com/shallow-vs-deep-copy-video-tutorial/

Page 65: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

• Are stable & fault tolerant• Can be shared freely

Immutables can even be shared freely, when using a lock free algorithm in

a multithreaded environment, where multiple actions happen in parallel.

Page 66: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables can be shared freely

• Are stable & fault tolerant• Can be shared freely

Many see this as the key benefit of Immutables. However, it is a very advanced subject,

so I won't go into detail here, but will probably show it at a later stage.

Page 67: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables work well as Map keys and Set elements

• Are stable & fault tolerant• Can be shared freely• Work well as Map keys and Set

elements

Finally, Immutable objects are also a perfect option to use as Map keys and Set elements,

since Map keys and Set elements must never change.

Page 68: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables work well as Map keys and Set elements

These are the main advantages of Immutables. Let’s also look at their disadvantages.

Page 69: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Disadvantages of Immutables

• May lead to performance problems

The biggest disadvantage of Immutable classes is that their use may lead to performance problems.

Let's see how.

Page 70: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables may lead to performance problems

Object

Immutables require a new object

Page 71: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables may lead to performance problems

for every distinct state they represent.

Page 72: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables may lead to performance problems

Therefore, the use of Immutables often increases the number of objects created.

Page 73: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables may lead to performance problems

Naturally, the more objects that are created, the more system resources will be used.

Page 74: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Immutables may lead to performance problems

However, this may not be a problem at all. There are many more influencing factors

as we will see later on.

Page 75: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

How to create an Immutable

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

So now that I’ve shown the value of an Immutable class. How can we actually make one?

Page 76: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

How to create an Immutable

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

To make a class immutable, we have to follow a few rules:

Page 77: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

1.Make all attributes private final.

First of all, we have to make all its attributes private and final

Page 78: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

private final String name; private final Destination destination;

1. Make all attributes private final

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}

Let’s illustrate this by looking at the ImmutableSpaceship class I introduced you to before.

Page 79: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

private final String name; private final Destination destination;

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}

We make the attributes private, so that no reference can be accessed from outside.

Page 80: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

private final String name; private final Destination destination;

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]} While private variables cannot be

accessed from outside the class, they can still be reassigned.

Page 81: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

private final String name; private final Destination destination;

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}

To prevent this we also have to make all variables final.

Page 82: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

private final String name; private final Destination destination;

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}Setting all internal reference variables to final –

clearly communicates our intent to make an immutable class.

Page 83: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

1. Make all attributes private final

private final String name; private final Destination destination;

public final class ImmutableSpaceship {

public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}

Should someone try to reassign a reference variable, a compiler error will occur.

Page 84: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

2. Don’t provide any methods that modify the object’s state

1.Make all attributes private and final.2.Don’t provide any methods that modify

the object’s state.

Okay. Second, we must not provide any methods

that modify the object’s state.

Page 85: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

2. Don’t provide any methods that modify the object’s state

1.Make all attributes private and final.2.Don’t provide any methods that modify

the object’s state.

This I have already briefly discussed at the beginning of this presentation, but now we will look at it more closely.

Page 86: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }

2. Don’t provide any methods that modify the object’s state

public final class ImmutableSpaceship { private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

For any change that you want to apply to your Immutable object,

you have to provide a method that returns a new object.

Page 87: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

2. Don’t provide any methods that modify the object’s state

public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }

public final class ImmutableSpaceship { private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}Attributes that do not change, like “name” in this case,

can be copied from our current object.

Page 88: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

2. Don’t provide any methods that modify the object’s state

public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }

public final class ImmutableSpaceship { private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

Attributes that do change, like “destination” in this case, have to be initialized with a new value instead.

Page 89: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

3. Ensure that the class can’t be extended

1.Make all attributes private and final.2.Don’t provide any methods that modify

the object’s state.3.Ensure that the class can’t be extended.

Let’s go on to the next rule. To further protect our class from being changed, we also have to prevent it from being extended.

Page 90: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

3. Ensure that the class can’t be extended

1.Make all attributes private and final.2.Don’t provide any methods that modify

the object’s state.3.Ensure that the class can’t be extended.

Extending a class would allow you to override its methods.

This would allow you to directly change the “unchangeable" object.

Page 91: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

3. Ensure that the class can’t be extended

1.Make all attributes private and final.2.Don’t provide any methods that modify

the object’s state.3.Ensure that the class can’t be extended.

Let's look at a code example to better illustrate this:

Page 92: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public class RomulanSpaceship extends ImmutableSpaceship {

@Override public RomulanSpaceship exploreGalaxy() { this.destination = Destination.OUTER_SPACE; return this; }

3. Ensure that the class can’t be extended

[…]}

private String name; private Destination destination;

public RomulanSpaceship(String name) { super(name); }

So here we have a RomulanSpaceship extending our ImmutableSpaceship.

Page 93: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

@Override public RomulanSpaceship exploreGalaxy() { this.destination = Destination.NEUTRAL_ZONE; return this; }

public class RomulanSpaceship extends ImmutableSpaceship {

3. Ensure that the class can’t be extended

[…]}

private String name; private Destination destination;

public RomulanSpaceship(String name) { super(name); }

Its overridden exploreGalaxy() method violates the rules of an Immutable,

as it directly changes the destination attribute.

Page 94: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

ImmutableSpaceship immutableSpaceship = new RomulanSpaceship("Battlequeen");

3. Ensure that the class can’t be extended

As RomulanSpaceship extends ImmutableSpaceship

Page 95: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

3. Ensure that the class can’t be extended

ImmutableSpaceship immutableSpaceship = new RomulanSpaceship("Battlequeen");

we can create an instance of a RomulanSpaceship,

Page 96: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

3. Ensure that the class can’t be extended

ImmutableSpaceship immutableSpaceship = new RomulanSpaceship("Battlequeen");

and assign it to an ImmutableSpaceship reference variable.

Page 97: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

ImmutableSpaceship immutableSpaceship = new RomulanSpaceship("Battlequeen");[…]immutableSpaceship.exploreGalaxy(); // internally changes the "immutable" Spaceship

3. Ensure that the class can’t be extended

Much later in the code, in a different class and method, we will call the exploreGalaxy() method on our ImmutableSpaceship instance -

Page 98: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

ImmutableSpaceship immutableSpaceship = new RomulanSpaceship("Battlequeen");[…]immutableSpaceship.exploreGalaxy(); // internally changes the "immutable" Spaceship

3. Ensure that the class can’t be extended

which, much to our concern, will internally change the spaceship instance,

which we expected to be unchangeable.

Page 99: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public final class ImmutableSpaceship {

3. Ensure that the class can’t be extended

private final String name; private final Destination destination; public ImmutableSpaceship(String name) { this.name = name; this.destination = Destination.NONE; } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; } public ImmutableSpaceship exploreGalaxy() { return new ImmutableSpaceship(name, Destination.OUTER_SPACE); }[…]}To prevent this, we just have to make our class final.

A final class can’t be extended, so it won’t be possible to override any method either.

Page 100: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

1.Make all attributes private and final.2.Don’t provide any methods that modify the

object’s state.3.Ensure that the class can’t be extended.4.Ensure exclusive access to any mutable

attributes.And now to the final rule – we have ensure exclusive access to any mutable

attributes.

Page 101: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Here you can see a representation of our spaceship object.

Name

Spaceship

DestinationName

Immutable

Page 102: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

The attribute “name” is of type String, which is an Immutable.

Name

Spaceship

DestinationName

Immutable

Page 103: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

As I've already shown you, you can freely share Immutable attributes -

Name

Spaceship

DestinationName

Immutable

Page 104: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Name

Spaceship

DestinationName

Immutable

Mutable

with other objects, as they cannot be changed.

Page 105: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

The Destination object, in this case, we’ll assume, is Mutable.

Page 106: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

Mutable

Anyone who holds a reference to it -

Page 107: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

Mutable

can alter it.

Page 108: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Immutable

Mutable

This will effectively alter our "Immutable" object.

Page 109: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

Mutable

4. Ensure exclusive access to any mutable attributes

In other words, it would not be immutable.

Page 110: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Mutable

So to protect our Immutable object -

Page 111: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Mutable

Spaceship

DestinationName

Immutable

we have to isolate the mutable destination attribute from the outside and prevent anyone from getting hold of it.

Page 112: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

Destination

MutableTo achieve this, we never obtain or return a direct reference to a destination object. Instead we create a deep copy and work with that

instead.

Page 113: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

DestinationDestination

MutableAs long as the mutable destination object

is never directly shared,

Page 114: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

DestinationDestination

Mutablea change inside an external object will not have any effect on our immutable object.

Page 115: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

Spaceship

DestinationName

Immutable

DestinationDestination

Mutable

Okay, talk is cheap, show me the code.

Page 116: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); }

4. Ensure exclusive access to any mutable attributes

private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

To ensure exclusive access to our mutable destination attribute,

Page 117: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

we have to check all public methods and constructors for any

incoming or outgoing Destination references.

Page 118: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

Let’s do this now.

Page 119: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

The public constructor does not receive any Destination reference.

Page 120: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

The Destination object it creates is safe, as it cannot be accessed from outside.

So the public constructor is good as it is.

Page 121: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

The public currentDestination() method returns a reference -

Page 122: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return destination; }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

to our internal Destination object, so this must be fixed.

Page 123: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

Now, instead of returning the real reference we create a deep copy

of our Destination object and return a reference to the copy instead.

Page 124: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

Finally, the public newDestination() method receives -

Page 125: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

a Destination reference -

Page 126: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

and forwards this reference to our private constructor.

Page 127: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

Now the private constructor directly stores the mutable Destination reference it receives.

Page 128: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

So, by following the execution path, we found that it is directly stored in the private

constructor.

Page 129: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = destination; }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

This must not be allowed.

Page 130: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

4. Ensure exclusive access to any mutable attributes

public ImmutableSpaceship newDestination(Destination newDestination) { return new ImmutableSpaceship(this.name, newDestination); }

public Destination currentDestination() { return new Destination(destination); }

public ImmutableSpaceship(String name) { this.name = name; this.destination = new Destination("NONE"); } private ImmutableSpaceship(String name, Destination destination) { this.name = name; this.destination = new Destination(destination); }

[…]}

public final class ImmutableSpaceship { private final String name; private final Destination destination;

To stop it immediately, we store a reference to a deep copy of the external Destination object.

Page 131: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

• What is an Immutable?• Advantages & disadvantages• How to create an Immutable• When to use Immutables

Okay. So I've shown you what an Immutable is, I've told you about its advantages and disadvantages,

and finally, I have demonstrated how to create an Immutable class.

Page 132: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

There is just one last thing I would like to tell you –

When should YOU actually use an Immutable class in your code?

Page 133: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

The question of whether you should design a specific class as an Immutable depends mainly on whether the performance of the

overall system is sufficient or not.

Page 134: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

This again depends on the nature of the system and all

aspects related to it. For example: What kind of

specific problem are you trying to solve?

Page 135: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

On what kind of hardware is your program running? Is it a desktop

or web application? It also depends on the internal structure of your code.

Page 136: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

For example: Of how many packages, classes and methods does your code consist of? As you can see, there is no simple answer to this very complex

question.

Page 137: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

Each case must be looked at individually.

As a general recommendation however,

I advise you to follow this approach:

Focus on designing a system that uses

immutables to the greatest possible extent.

Page 138: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

Facilitate their use by designing simple

classes with few attributes and methods.

Immutables may become a burden

when they are too complex. Simplicity is key.

Page 139: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

In this endeavor, Clean Code and Immutables are a well matched pair, reinforcing each other.

Page 140: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

In the majority of cases, this approach will lead to a

system that exceeds all requirements.

Page 141: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

If however, testing reveals that you have not achieved

satisfactory performance, relax the immutability rules gradually.

Page 142: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

As much as necessary, but as little as possible.

Page 143: Immutables in Java

Copyright © 2016 Marcus Bielwww.marcus-biel.com

When to use Immutables

Copyright © 2016 Marcus Biel

All rights reserved.


Recommended