I have a Move
class, which is immutable (basically it's just two ints).
The I have class Moves
with constants:
public class Moves {
public static final Move NW = Move.make(-1, -1);
public static final Move N = Move.make(0, -1);
public static final Move NE = Move.make(1, -1);
public static final Move E = Move.make(1, 0);
public static final Move SE = Move.make(1, 1);
public static final Move S = Move.make(0, 1);
public static final Move SW = Move.make(-1, 1);
public static final Move W = Move.make(-1, 0);
public final static Move[] ALL = {
NW, N, NE, E, SE, S, SW, W
};
public final static Move[] CARDINAL = {
N, E, S, W
};
}
I need the arrays for methods such as:
public void walkToRandomSide(Move[] possibleMoves)
It works nicely, but - obviously - the elements of ALL
and CARDINAL
can be changed anytime by anyone. I know the elements cannot be made final, of course.
That is bad - I want this to be a part of a library and as stable and predictable as possible.
How would I work around this? Make a method that creates a new array each time?
No, just avoid using arrays. Arrays are always mutable, and even if you create a new array each time, that means your callers will have to perform defensive copies if they pass the sets around.
Firstly, I'd change your Move
class to an enum as Steve suggested. Then anyone can use EnumSet.allOf
.
Secondly, for CARDINAL
I would either use Collections.unmodifiableList
to wrap a list that you'd created internally (and know that you're never going to modify yourself), or use a type which explicitly talks about immutability, such as ImmutableList
from Guava (or perhaps ImmutableSet
, depending on whether ordering is important or not).
The benefit of using a separate type is that you can then make it clear to callers that it is immutable, rather than just documenting that the list that's been returned happens to be immutable. While usually it's a good idea to use an interface as the return type, here it's worth communicating a very concrete guarantee in the type system - a guarantee that callers can use in their code as well.
See more on this question at Stackoverflow