Java immutable class rules

Is the class below immutable:

final class MyClass { private final int[] array; public MyClass(int[] array){ this.array = array; } } 
+4
source share
5 answers

No, this is not because the elements of the array can still be changed.

 int[] v1 = new int[10]; MyClass v2 = new MyClass(v1); v1[0] = 42; // mutation visible to MyClass1 
+21
source

My two cents on immutability rules (which I kept from reading Effective Java is a great book!):

  • Do not provide methods that can change the state of an object.
  • Make all your fields final.
  • Make sure your class is not extensible.
  • Make all fields private.
  • Provide exclusive access to any fields or components of your class that you can modify. Essentially, this applies to your situation (as explained by JaredPar ). The person who uses your class still has a reference to your array. The opposite is when you return a reference to a component of your class. In this case, always create protective copies. In your case, you should not assign a link. Instead, copy the array that the user of your class provides into your internal component.
+6
source

"Constant" is an agreement between a programmer and himself. This convention can be more or less enforced by the compiler.

Instances of a class are "immutable" if they do not change during the normal course of application code execution. In some cases, we know that they do not change because the code actually prohibits this; in other cases, this is only part of how we use the class. For example, the java.util.Date instance is formally changed (it has the setTime() method on it), but it is customary to process it as if it were unchanged; this is just a common convention that the Date.setTime() method should not be called.

As additional notes:

  • Immutability is often considered in terms of "external characteristics." For example, Java String documented as immutable (as Javadoc says). But if you look at the source code, you will see that the String instance contains a private field named hash , which may change over time: this is the cache for the value returned by hashCode() . We still say that String is immutable because the hash field is an internal optimization that has no effect visible from the outside.
  • When reflected, the most private instance fields can be changed (including those marked as final ) if the programmer so desires. Not that it's a good idea: it may violate the assumptions used by other code fragments using the specified instance. As I said, immutability is an agreement: if a programmer wants to fight on his own, then it can, but it can have adverse side effects on performance ...
  • Most Java values ​​are actually references. You must determine if the reference object is part of what you consider to be "instance content". In your class, you have a field that refers to an array of integers. If the contents of this array are changed later, do you think this violates the immutability of your MyClass instance? There is no general answer to this question.
+1
source

It is not possible to make an array immutable. That is, there is no way to save any client code in setting up or deleting or adding elements to an array.

Here is a really immutable alternative:

 private static class MyClass { private List<Integer> list; private MyClass(final int[] array) { final List<Integer> tmplist = new ArrayList<Integer>(array.length); for (int i : array) { tmplist.add(array[i]); } this.list = Collections.unmodifiableList(tmplist); } } 
0
source

To make a class immutable, you need to ensure that all fields on it are final and that the types of these fields are also immutable.

It may be a pain that needs to be remembered, but there is a tool that will help you.

Pure4J provides the @ImmutableValue annotation that you can add to an interface or class.

There is a maven plugin for checking at compile time, after which you follow the rules of immutability.

Hope this helps.

0
source

Source: https://habr.com/ru/post/1314226/


All Articles