web-dev-qa-db-fra.com

BigDecimal - pour utiliser new ou valueOf

Je suis tombé sur deux façons d'obtenir un objet BigDecimal d'un double d.

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

Quelle serait la meilleure approche? Est-ce que valueOf créerait un nouvel objet?

En général (pas seulement BigDecimal), qu'est-ce qui est recommandé - nouveau ou valueOf?

Merci.

85
Manish Mulani

Ce sont deux questions distinctes: "Que devrais-je utiliser pour BigDecimal?" et "Qu'est-ce que je fais en général?"

Pour BigDecimal: c'est un peu délicat, car ils ne font pas la même chose . BigDecimal.valueOf(double) utilisera la canonique String représentation de la valeur double passé pour instancier l'objet BigDecimal. En d'autres termes: la valeur de l'objet BigDecimal sera celle que vous verrez lorsque vous ferez System.out.println(d).

Si vous utilisez toutefois new BigDecimal(d) , le BigDecimal essaiera de représenter le double valeur aussi précisément que possible. Cela généralement entraînera le stockage de beaucoup plus de chiffres que vous ne le souhaitez. Strictement parlant, c'est plus correct que valueOf(), mais c'est beaucoup moins intuitif.

Il y a une bonne explication à cela dans le JavaDoc:

Les résultats de ce constructeur peuvent être quelque peu imprévisibles. On peut supposer que l'écriture de new BigDecimal(0.1) in Java crée un BigDecimal qui est exactement égal à 0,1 (une valeur non échelonnée de 1, avec une échelle de 1) , mais elle est en réalité égale à 0.10000000000000000000055511151231257827021181583404541015625, car 0,1 ne peut pas être représenté exactement comme un double (ou, en l'occurrence, comme une fraction binaire de longueur finie). Ainsi, la valeur transmise est transmise. pour le constructeur n’est pas exactement égal à 0,1, malgré les apparences.

En général, si le résultat est le même (c'est-à-dire pas dans le cas de BigDecimal, mais dans la plupart des autres cas), alors valueOf() devrait être préféré : il peut faire la mise en cache de valeurs communes (comme indiqué sur Integer.valueOf() ) et peut même changer le comportement de mise en cache sans que l'appelant ait à être changé. new will toujours instancie une nouvelle valeur, même si cela n'est pas nécessaire (meilleur exemple: new Boolean(true) vs Boolean.valueOf(true)).

145
Joachim Sauer

Si vous utilisez vos objets BigDecimal pour stocker des valeurs monétaires, je vous recommande vivement de faire [~ # ~] et non [~ # ~] implique des valeurs doubles n'importe où dans leurs calculs.

Comme indiqué dans une autre réponse, il existe des problèmes d’exactitude connus avec des valeurs doubles qui reviendront vous hanter énormément.

Une fois que vous avez dépassé cela, la réponse à votre question est simple. Utilisez toujours la méthode constructeur avec la valeur String comme argument du constructeur, car il n'y a pas de méthode valueOf pour String.

Si vous voulez une preuve, essayez ce qui suit:

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

Vous obtiendrez le résultat suivant:

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01

Voir aussi ceci question connexe

43
DuncanKinnear

Fondamentalement, valueOf (double val) fait juste ceci:

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

Par conséquent -> ouais, un nouvel objet sera créé :).

En général, je pense que cela dépend de votre style de codage. Je ne voudrais pas mélanger valueOf et "new", si les deux sont le même résultat.

4
DXTR66