1

I've currently seen this constructor:

public ImmutableClass( final long id, final String[] arrayOfStrings,
    final Collection< String > collectionOfString) {

    this.id = id;
    this.arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
    this.collectionOfString = new ArrayList<>( collectionOfString );
}

I have never seen something like that before. It was argued that it is for the "Immutability" of the Class and it makes sure that the state can't be modified from outside.

So, does this make sense or what is this?

Furthermore, I wanted to know why the arguments in this code are marked as final?

Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • 3
    I think you mean `immutability`, not `immunability`, the latter which sounds like you are trying to make your code virus proof :-) – Tim Biegeleisen Jun 03 '18 at 13:20
  • To achieve true immutability, it would be better to first deep-copy the list and then construct an immutable list (via [`Lists.of(...)`](https://docs.oracle.com/javase/10/docs/api/java/util/List.html#of(E...))) from the deep-copy list and assing this to `collectionsOfString` – Turing85 Jun 03 '18 at 13:33

1 Answers1

3

So, does this make sense or what is this?

This will make a deep copy of String array argument.

arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );

This will copy the input array to inner variable, which effectively prevent modification ImmutableClass.arrayOfStrings field by modifying the supplied array.

If you simply assign it like this:

public ImmutableClass( final long id, final String[] input,
final Collection< String > collectionOfString) {

    this.id = id;
    this.arrayOfStrings = input;
...
}

Then when you modify the input: input[0] = "new string", the inner arrayOfStrings got modified too, which breaks the Immutable characteristic

The same logic is applied to collectionOfString

Furthermore, I wanted to know why the arguments in this code are marked as final?

It is a guard to prevent reassign supplied parameter to other value.

Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51
  • 1
    "*This will make a deep copy of input argument.*" - [No, it won't](https://ideone.com/IFU76W). Even implementing the broken `Cloneable` interface will not help in this case. You have to make the copies manually. – Turing85 Jun 03 '18 at 13:46
  • Sorry I don't understand what you're saying. My point is the code doing a deep copy of input array to prevent modification from outside. What's conflicting with your point? – Mạnh Quyết Nguyễn Jun 03 '18 at 13:47
  • My code is. If I have any reference to any object that resides in the input array, I can mutate this object and these changes will be reflected in the copied version. `Arrays.copyOf(...)` does not create a deep copy. – Turing85 Jun 03 '18 at 13:51
  • But this is `String`. I did not say it applied to all object :D. I will make it more clear – Mạnh Quyết Nguyễn Jun 03 '18 at 13:53
  • 2
    You say is a deep copy, and this is false. `Arrays.copyOf(...)` only copies the references, not the objects. – Turing85 Jun 03 '18 at 13:58
  • `Arrays.copyOf` copy the input array String to a new array. It's a deep copy of that String array – Mạnh Quyết Nguyễn Jun 03 '18 at 13:59
  • If it were, then, [in the example I gave above](https://ideone.com/IFU76W), the change to `singleEntryInData` should not be reflected in `copy`. – Turing85 Jun 03 '18 at 14:01
  • Till now I don't know what you're talking about. For String/int/char array, it's deep copy. That method is backed by `System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));`, it's not a simple reference copy – Mạnh Quyết Nguyễn Jun 03 '18 at 14:04
  • `System.arraycopy(...)` is implemented as native method call, there is no evidence that there is a "special version" of `System.arraycopy(...)` for `String`s or any other type, all reference-types are handled equally. The topic is also discussed and explained in [this question](https://stackoverflow.com/questions/15135104/system-arraycopy-copies-object-or-reference-to-object). `System.arraycopy(...)` and `Arrays.copyOf(...)` create shallow copies for reference-types. – Turing85 Jun 03 '18 at 14:09
  • String is immutable so it's effectively do a deep copy. For primitive type, it copies the values so deep copy too. You're right about the reference type, it's not a deep copy. Read my above comment please. – Mạnh Quyết Nguyễn Jun 03 '18 at 14:17