BigDecimal: para usar nuevo o valueOf

Encontré dos maneras de obtener un objeto BigDecimal de una doble d.

1. new BigDecimal(d) 2. BigDecimal.valueOf(d) 

¿Cuál sería un mejor enfoque? ¿ValueOf crearía un nuevo objeto?

En general (no solo BigDecimal), ¿qué se recomienda, nuevo o valueOf?

Gracias.

Esas son dos preguntas separadas: “¿Qué debería usar para BigDecimal ?” y “¿Qué hago en general?”

Para BigDecimal : esto es un poco complicado, porque no hacen lo mismo . BigDecimal.valueOf(double) utilizará la representación de String canónica del valor double pasado para crear una instancia del objeto BigDecimal . En otras palabras: el valor del objeto BigDecimal será lo que verá cuando haga System.out.println(d) .

Sin embargo, si usa un new BigDecimal(d) , BigDecimal intentará representar el double valor con la mayor precisión posible . Esto generalmente dará como resultado que se almacenen muchos más dígitos de los que desea. Estrictamente hablando, es más correcto que valueOf() , pero es mucho menos intuitivo.

Hay una buena explicación de esto en JavaDoc:

Los resultados de este constructor pueden ser algo impredecibles. Uno podría suponer que escribir un new BigDecimal(0.1) en Java crea un BigDecimal que es exactamente igual a 0.1 (un valor sin escala de 1, con una escala de 1), pero en realidad es igual a 0.1000000000000000055511151231257827021181583404541015625. Esto se debe a que 0.1 no se puede representar exactamente como un double (o, para el caso, como una fracción binaria de cualquier longitud finita). Por lo tanto, el valor que se transfiere al constructor no es exactamente igual a 0.1, a pesar de las apariencias.

En general, si el resultado es el mismo (es decir, no en el caso de BigDecimal , sino en la mayoría de los demás casos), se debe preferir valueOf() : puede hacer el almacenamiento en caché de valores comunes (como se ve en Integer.valueOf() ) e incluso puede cambiar el comportamiento de almacenamiento en caché sin tener que cambiar la persona que llama. new siempre creará una instancia de un nuevo valor, incluso si no es necesario (mejor ejemplo: new Boolean(true) vs. Boolean.valueOf(true) ).

Si está utilizando sus objetos BigDecimal para almacenar valores de moneda, le recomiendo encarecidamente que NO implique valores dobles en ningún lugar de sus cálculos.

Como se indica en otra respuesta, existen problemas de precisión conocidos con valores dobles y estos volverán a perseguirte a lo grande.

Una vez que superas eso, la respuesta a tu pregunta es simple. Siempre use el método constructor con el valor String como argumento para el constructor, ya que no hay ningún método valueOf para String .

Si quieres una prueba, prueba lo siguiente:

 BigDecimal bd1 = new BigDecimal(0.01); BigDecimal bd2 = new BigDecimal("0.01"); System.out.println("bd1 = " + bd1); System.out.println("bd2 = " + bd2); 

Obtendrás el siguiente resultado:

 bd1 = 0.01000000000000000020816681711721685132943093776702880859375 bd2 = 0.01 

Ver también esta pregunta relacionada

Básicamente valueOf (double val) solo hace esto:

return new BigDecimal(Double.toString(val));

Por lo tanto, -> sí, se creará un nuevo objeto :).

En general, creo que depende de tu estilo de encoding. No mezclaría valueOf y “new”, si ambos son el mismo resultado.