As a warm-up, test your knowledge of BigInteger. What
does this program print?
import java.math.BigInteger;
public class BigProblem {
public static void main(String[] args) {
BigInteger fiveThousand = new BigInteger("5000");
BigInteger fiftyThousand = new BigInteger("50000");
BigInteger fiveHundredThousand
= new BigInteger("500000");
BigInteger total = BigInteger.ZERO;
total.add(fiveThousand);
total.add(fiftyThousand);
total.add(fiveHundredThousand);
System.out.println(total);
}
}
Solution 56: Big Problem
You might think that this program prints
555000. After all, it sets total to the BigInteger
representation for 0 and then adds 5,000, 50,000, and 500,000. If you ran the
program, you found that it doesn't print 555000 but 0.
Apparently all that addition has no effect on total.
There is a good reason for this: BigInteger instances are immutable. So are
instances of String, BigDecimal, and the wrapper types:
Integer, Long, Short, Byte,
Character, Boolean, Float, and Double. You
can't change their values. Instead of modifying existing instances, operations
on these types return new instances. At first, immutable types might seem
unnatural, but they have many advantages over their mutable counterparts.
Immutable types are easier to design, implement, and use; they are less error
prone and more secure [EJ Item 13].
To perform a computation on a variable containing a reference
to an immutable object, assign the result of the computation to the variable.
Doing this yields the following program, which prints the expected result of
555000:
import java.math.BigInteger;
public class BigProblem {
public static void main(String [] args) throws Exception {
BigInteger fiveThousand = new BigInteger("5000");
BigInteger fiftyThousand = new BigInteger("50000");
BigInteger fiveHundredThousand
= new BigInteger("500000");
BigInteger total = BigInteger.ZERO;
total = total.add(fiveThousand);
total = total.add(fiftyThousand);
total = total.add(fiveHundredThousand);
System.out.println(total);
}
}
The lesson of this puzzle is: Do not
be misled into thinking that immutable types are mutable. This is a
common error among beginning Java programmers. In fairness, the names of some
methods in Java's immutable types help to lead them astray. Names like
add, subtract, and negate suggest that these methods
mutate the instance on which they're invoked. Better names would be
plus, minus, and negation.
A lesson for API designers, then, is:
When naming methods for immutable types, prefer prepositions and nouns to verbs.
Prepositions are appropriate for methods with parameters and nouns for
parameterless methods. A lesson for language designers is, as in Puzzle 2, that it might
be worth offering limited support for operator overloading so that arithmetic
operators can be made to work with numerical reference types, such as
BigInteger. Not even a beginner would think that evaluating the
expression total + fiveThousand would have any effect on the value of
total.
No comments:
Post a Comment
Your comments are welcome!