Big Problem
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 : 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 .
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 Problem of change, 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