17

In Java, is new a BigDecimal from another bigDecimal.toString() always equals? For example

    BigDecimal a = new BigDecimal("1.23");
    BigDecimal b = new BigDecimal(a.toString());

    System.out.println(a.compareTo(b) == 0); // always true?

I know BigDecimal is immutable, but i want to know if there is any good way to clone a BigDecimal object?

andyf
  • 3,262
  • 3
  • 23
  • 37
  • not much likely, you could always go for a shallow copy though – Swastik Padhi Oct 28 '15 at 01:18
  • 1
    @CrakC could you show a example for shallow copy? – andyf Oct 28 '15 at 01:20
  • _if there is any good way to clone a BigDecimal object_ Do you mean only **from its `toString()` representation**? – Sotirios Delimanolis Oct 28 '15 at 01:20
  • @SotiriosDelimanolis I found toString() may works, but there should be any other good way. – andyf Oct 28 '15 at 01:22
  • There's a copy constructor as well. Any of the `add(BigDecimal.ZERO)`, `multiply(BigDecimal.ONE)` should work as well. – Sotirios Delimanolis Oct 28 '15 at 01:22
  • @SotiriosDelimanolis thanks very much. `add(BigDecimal.ZERO)` , `multiply(BigDecimal.ONE)` is very good idea. – andyf Oct 28 '15 at 01:25
  • 1
    @andyf I don't think it is. I can't find any guarantee that a new object is returned. – Paul Boddington Oct 28 '15 at 01:26
  • @SotiriosDelimanolis there isn't a copy constructor, i.e one that takes BigDecimal as an argument – Sleiman Jneidi Oct 28 '15 at 01:26
  • @SleimanJneidi You're right. I was looking at one with `BigInteger`. Thanks. – Sotirios Delimanolis Oct 28 '15 at 01:27
  • 1
    @andyf I just checked, and `BigDecimal.ZERO.add(BigDecimal.ZERO)` does not return a new object. – Paul Boddington Oct 28 '15 at 01:28
  • 1
    @SotiriosDelimanolis yeah, it doesn't need one because it is immutable – Sleiman Jneidi Oct 28 '15 at 01:28
  • 1
    @PaulBoddington Thanks. Yes `BigDecimal.ZERO.add(BigDecimal.ZERO) ` does not return a new object. may be its because the result is BigDecimal.ZERO too. But as I try other NOT ZERO value return a new object. – andyf Oct 28 '15 at 01:54
  • @andyf I wouldn't rely on that. Looking at the source code it seems common values are cached. Also in a future version they could change it so that `add(BigDecimal.ZERO)` always just does `return this;`. I would stick to `new BigDecimal(bigDecimal.toString());`. – Paul Boddington Oct 28 '15 at 01:57
  • @PaulBoddington Indeed. should use `new BigDecimal(bigDecimal.toString())` for safety coding. This problem may similar to `Integer.valueOf(127) == Integer.valueOf(127)` but `Integer.valueOf(128) != Integer.valueOf(128)` – andyf Oct 28 '15 at 02:22

3 Answers3

29

Yes you can assume so. From the BigDecimal.toString docs

If that string representation is converted back to a BigDecimal using the BigDecimal(String) constructor, then the original value will be recovered.

However you can safely share the same object because it is immutable and copying is not required

Sleiman Jneidi
  • 22,907
  • 14
  • 56
  • 77
6

Just a remark : BigDecimal is not final so it can be extended by a mutable class. Making a defensive copy can therefore be required in some use cases.

The BigDecimal.toString() method can be used :

 * There is a one-to-one mapping between the distinguishable
 * {@code BigDecimal} values and the result of this conversion.
 * That is, every distinguishable {@code BigDecimal} value
 * (unscaled value and scale) has a unique string representation
 * as a result of using {@code toString}.  If that string
 * representation is converted back to a {@code BigDecimal} using
 * the {@link #BigDecimal(String)} constructor, then the original
 * value will be recovered.

Here an example of code making a defensive copy of BigDecimal :

public static BigDecimal safeInstance(BigDecimal val) { 
    return val.getClass() == BigDecimal.class ? 
    val : new BigDecimal(val.toString()); 
}

But does it make sense ? If a class extends the BigDecimal class you cannot be sure it does not extend its toString() method without respecting the contract...

Probably it's better to invalidate any extension of BigDecimal :

public static BigDecimal safeInstance(BigDecimal val) { 
    if (val.getClass() != BigDecimal.class) {
        //TODO throw exception
    }
    return val; 
}
Greg D
  • 331
  • 3
  • 3
5

One simple way would be to add ZERO

BigDecimal a = new BigDecimal("1.23");
BigDecimal b = a.add(BigDecimal.ZERO);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
user3871424
  • 244
  • 4
  • 4