下面仍然是經(jīng)典的Hello World程序的另一個(gè)變種。那么,這個(gè)變種將打印什么呢?
public class Null {
public static void greet() {
System.out.println("Hello world!");
}
public static void main(String[] args) {
((Null) null).greet();
}
}
這個(gè)程序看起來似乎應(yīng)該拋出NullPointerExceptioin異常,因?yàn)槠鋗ain方法是在常量null上調(diào)用greet方法,而你是不可以在null上調(diào)用方法的,對嗎?嗯,某些時(shí)候是可以的。如果你運(yùn)次該程序,就會(huì)發(fā)現(xiàn)它打印出了“Hello World!”
理解本謎題的關(guān)鍵是Null.greet是一個(gè)靜態(tài)方法。正如你在謎題48中所看到的,在靜態(tài)方法的調(diào)用中,使用表達(dá)式作為其限定符并非是一個(gè)好主意,而這也正是問題之所在。不僅表達(dá)式的值所引用的對象的運(yùn)行期類型在確定哪一個(gè)方法將被調(diào)用時(shí)并不起任何作用,而且如果對象有標(biāo)識的話,其標(biāo)識也不起任何作用。在本例中,沒有任何對象,但是這并不會(huì)造成任何區(qū)別。靜態(tài)方法調(diào)用的限定表達(dá)式是可以計(jì)算的,但是它的值將被忽略。沒有任何要求其值為非空的限制。
要想消除該程序中的混亂,你可以用它的類作為限定符來調(diào)用greet方法:
public static void main(String[] args) {
Null.greet();
}
然而更好的方式是完全消除限定符:
public static void main(String[] args) {
greet();
}
總之,本謎題的教訓(xùn)與謎題48的完全相同:要么用某種類型來限定靜態(tài)方法調(diào)用,要么就壓根不要限定它們。對語言設(shè)計(jì)者來說,應(yīng)該不允許用表達(dá)式來污染靜態(tài)方法調(diào)用的可能性存在,因?yàn)樗鼈冎粫?huì)產(chǎn)生混亂。
public class Null {
public static void greet() {
System.out.println("Hello world!");
}
public static void main(String[] args) {
((Null) null).greet();
}
}
這個(gè)程序看起來似乎應(yīng)該拋出NullPointerExceptioin異常,因?yàn)槠鋗ain方法是在常量null上調(diào)用greet方法,而你是不可以在null上調(diào)用方法的,對嗎?嗯,某些時(shí)候是可以的。如果你運(yùn)次該程序,就會(huì)發(fā)現(xiàn)它打印出了“Hello World!”
理解本謎題的關(guān)鍵是Null.greet是一個(gè)靜態(tài)方法。正如你在謎題48中所看到的,在靜態(tài)方法的調(diào)用中,使用表達(dá)式作為其限定符并非是一個(gè)好主意,而這也正是問題之所在。不僅表達(dá)式的值所引用的對象的運(yùn)行期類型在確定哪一個(gè)方法將被調(diào)用時(shí)并不起任何作用,而且如果對象有標(biāo)識的話,其標(biāo)識也不起任何作用。在本例中,沒有任何對象,但是這并不會(huì)造成任何區(qū)別。靜態(tài)方法調(diào)用的限定表達(dá)式是可以計(jì)算的,但是它的值將被忽略。沒有任何要求其值為非空的限制。
要想消除該程序中的混亂,你可以用它的類作為限定符來調(diào)用greet方法:
public static void main(String[] args) {
Null.greet();
}
然而更好的方式是完全消除限定符:
public static void main(String[] args) {
greet();
}
總之,本謎題的教訓(xùn)與謎題48的完全相同:要么用某種類型來限定靜態(tài)方法調(diào)用,要么就壓根不要限定它們。對語言設(shè)計(jì)者來說,應(yīng)該不允許用表達(dá)式來污染靜態(tài)方法調(diào)用的可能性存在,因?yàn)樗鼈冎粫?huì)產(chǎn)生混亂。

