Are immutable copier types needed?

Say I have an immutable DecimalNumber class:

 public final class DecimalNumber { public final String str; public DecimalNumber(String str) { this.str = str; } public DecimalNumber(DecimalNumber copy) { this(copy.str); } public boolean isZero() {...} public DecimalNumber add(DecimalNumber other) {...} ... } 

and I decided to implement add as follows:

 public DecimalNumber add(DecimalNumber other) { if (other.isZero()) return /* the same object */ ... } 

Should I return this (less memory usage) or the copied object new DecimalNumber(this) ?

I would have thought that just returning this should be fine, but is there ever a usefulness or reason for creating a new object, or is it ever preferable?

+5
source share
5 answers

If the class is immutable and final, you can return this .

If this is not final, you cannot be sure that the this instance is truly immutable. Perhaps you are really dealing with a subclass that adds mutable state.

Note that a class is really immutable if:

  • All its fields are final, even private. (Due to the Java memory model allowing other threads to see incomplete / default values ​​for non-final fields, not a finite field with only a getter is missing.)
  • All its fields are either immutable classes themselves or access to them is limited, so you can be sure that they will never be changed.

In your case, these two conditions are satisfied, since String is an immutable class. If you know that no subclasses of your class exist, you can (in fact, should IMHO) return this . To make sure that subclasses of your class do not exist, you can make it final .

+2
source

why do you feel weird in returning this ?

If you return a new object, you won’t need an if , so returning new DecimalNumber(this) is not a parameter at all!

+1
source

As you set the object immutable, we need to create another copy when we change . But here adding zero will not change the value of the object. Therefore, we can return the same object.

Consider the concat() code from String.java for reference:

 public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } char buf[] = new char[count + otherLen]; getChars(0, count, buf, 0); str.getChars(0, otherLen, buf, count); return new String(0, count + otherLen, buf); } 

As you can see, there is no harm in returning the same object.

+1
source

There is no need to ever make a copy of an immutable value object. Since it is unchanged, both the original and the copy will be equivalent for the whole time, and thus, the presence of two copies is pointless.

In your example, not only do I return this , I would take another step and completely delete your copy constructor.

As an example, the Java String class actually has a copy constructor. But all this is done leads to the creation of code by inexperienced developers who either do not understand that they are immutable (or do not understand what this implies), so they make new String(aString) or new String("Hello") , which does nothing but empty memory and processor cycles.

+1
source

I would return this if the object is really immutable. You just do not need two instances that are sure to be equal.

https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

0
source

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


All Articles