Java Reference
In-Depth Information
alternatives. For example, let's say that a path is a collection of lines, so here's the defini-
tion of an
ImmutablePath
:
@Immutable
class ImmutablePath {
List<ImmutableLine> segments = []
}
ThistimeIcan'tjustdeclarethesegmentsvariableusing
def
.IfIwantthe@
Immutable
annotation to work I need to specify that I'm using some sort of collection. On the
right-hand side of the
segments
definition I still just have
[]
, which normally means
an instance of
java.util.ArrayList
. In this case, however, what I actually get
(by printing
segments.class.name
) is
java.util.Collections$UnmodifiableRandomAccessList
, believe it or
not. The
Collections
class has utility methods like
unmodifiableList
that take
a regular list and return a new list that can't be changed, but to be honest I wouldn't have
necessarily expected it to be a
RandomAccessList
in this case. It doesn't make any dif-
ference what the actual class is, of course, as long as the contract is maintained.
Speaking of that contract, those unmodifiable methods in
Collections
don't remove
the available mutator methods. Instead, they wrap them and throw an
Unsuppor-
ted-OperationException
if they're accessed. That's arguably a strange way to im-
plement an interface, but so be it. The Spock test for this class is shown in the following
listing. Everything works as expected. It takes some doing to build up all the immutable
objects needed to create an
ImmutablePath
instance, but once everything is set it all
works.
Listing 4.9. A Spock test for the
ImmutablePath
class
class ImmutablePathTest extends Specification {
ImmutablePath path
def setup() {
def lines = []
ImmutablePoint p1 = new ImmutablePoint(x:0,y:0)
ImmutablePoint p2 = new ImmutablePoint(x:3,y:0)
ImmutablePoint p3 = new ImmutablePoint(x:0,y:4)
lines << new ImmutableLine(start:p1,end:p2)
lines << new ImmutableLine(start:p2,end:p3)
lines << new ImmutableLine(start:p3,end:p1)
path = new ImmutablePath(segments:lines)
}