作為一項(xiàng)熱身活動(dòng),我們來測(cè)試一下你對(duì)BigInteger的了解程度。下面這個(gè)程序?qū)⒋蛴〕鍪裁茨兀?BR> 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);
}
}
你可能會(huì)認(rèn)為這個(gè)程序會(huì)打印出555000。畢竟,它將total設(shè)置為用BigInteger表示的0,然后將5,000、50,000和500,000加到了這個(gè)變量上。如果你運(yùn)行該程序,你就會(huì)發(fā)現(xiàn)它打印的不是555000,而是0。很明顯,所有這些加法對(duì)total沒有產(chǎn)生任何影響。
對(duì)此有一個(gè)很好理由可以解釋:BigInteger實(shí)例是不可變的。String、BigDecimal以及包裝器類型:Integer、Long、Short、Byte、Character、Boolean、Float和Double也是如此,你不能修改它們的值。我們不能修改現(xiàn)有實(shí)例的值,對(duì)這些類型的操作將返回新的實(shí)例。起先,不可變類型看起來可能很不自然,但是它們具有很多勝過與其向?qū)?yīng)的可變類型的優(yōu)勢(shì)。不可變類型更容易設(shè)計(jì)、實(shí)現(xiàn)和使用;它們出錯(cuò)的可能性更小,并且更加安全[EJ Item 13]。
為了在一個(gè)包含對(duì)不可變對(duì)象引用的變量上執(zhí)行計(jì)算,我們需要將計(jì)算的結(jié)果賦值給該變量。這樣做就會(huì)產(chǎn)生下面的程序,它將打印出我們所期望的555000:
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 = total.add(fiveThousand);
total = total.add(fiftyThousand);
total = total.add(fiveHundredThousand);
System.out.println(total);
}
}
本謎題的教訓(xùn)是:不要被誤導(dǎo),認(rèn)為不可變類型是可變的。這是一個(gè)在剛?cè)腴T的Java程序員中很常見的錯(cuò)誤。公正地說,Java不可變類型的某些方法名促使我們走上了歧途。像add、subtract和negate之類的名字似乎是在暗示這些方法將修改它們所調(diào)用的實(shí)例。也許plus、minus和negation才是更好的名字。
對(duì)API設(shè)計(jì)來說,其教訓(xùn)是:在命名不可變類型的方法時(shí),應(yīng)該優(yōu)選介詞和名詞,而不是動(dòng)詞。介詞適用于帶有參數(shù)的方法,而名詞適用于不帶參數(shù)的方法。對(duì)語言設(shè)計(jì)者而言,其教訓(xùn)與謎題2相同,那就是應(yīng)該考慮對(duì)操作符重載提供有限的支持,這樣算數(shù)操作符就可以作用于諸如BigInteger這樣的數(shù)值型的引用類型。由此,即使是初學(xué)者也不會(huì)認(rèn)為計(jì)算表達(dá)式total + fiveThousand將會(huì)對(duì)total的值產(chǎn)生任何影響。
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);
}
}
你可能會(huì)認(rèn)為這個(gè)程序會(huì)打印出555000。畢竟,它將total設(shè)置為用BigInteger表示的0,然后將5,000、50,000和500,000加到了這個(gè)變量上。如果你運(yùn)行該程序,你就會(huì)發(fā)現(xiàn)它打印的不是555000,而是0。很明顯,所有這些加法對(duì)total沒有產(chǎn)生任何影響。
對(duì)此有一個(gè)很好理由可以解釋:BigInteger實(shí)例是不可變的。String、BigDecimal以及包裝器類型:Integer、Long、Short、Byte、Character、Boolean、Float和Double也是如此,你不能修改它們的值。我們不能修改現(xiàn)有實(shí)例的值,對(duì)這些類型的操作將返回新的實(shí)例。起先,不可變類型看起來可能很不自然,但是它們具有很多勝過與其向?qū)?yīng)的可變類型的優(yōu)勢(shì)。不可變類型更容易設(shè)計(jì)、實(shí)現(xiàn)和使用;它們出錯(cuò)的可能性更小,并且更加安全[EJ Item 13]。
為了在一個(gè)包含對(duì)不可變對(duì)象引用的變量上執(zhí)行計(jì)算,我們需要將計(jì)算的結(jié)果賦值給該變量。這樣做就會(huì)產(chǎn)生下面的程序,它將打印出我們所期望的555000:
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 = total.add(fiveThousand);
total = total.add(fiftyThousand);
total = total.add(fiveHundredThousand);
System.out.println(total);
}
}
本謎題的教訓(xùn)是:不要被誤導(dǎo),認(rèn)為不可變類型是可變的。這是一個(gè)在剛?cè)腴T的Java程序員中很常見的錯(cuò)誤。公正地說,Java不可變類型的某些方法名促使我們走上了歧途。像add、subtract和negate之類的名字似乎是在暗示這些方法將修改它們所調(diào)用的實(shí)例。也許plus、minus和negation才是更好的名字。
對(duì)API設(shè)計(jì)來說,其教訓(xùn)是:在命名不可變類型的方法時(shí),應(yīng)該優(yōu)選介詞和名詞,而不是動(dòng)詞。介詞適用于帶有參數(shù)的方法,而名詞適用于不帶參數(shù)的方法。對(duì)語言設(shè)計(jì)者而言,其教訓(xùn)與謎題2相同,那就是應(yīng)該考慮對(duì)操作符重載提供有限的支持,這樣算數(shù)操作符就可以作用于諸如BigInteger這樣的數(shù)值型的引用類型。由此,即使是初學(xué)者也不會(huì)認(rèn)為計(jì)算表達(dá)式total + fiveThousand將會(huì)對(duì)total的值產(chǎn)生任何影響。