假設(shè)你不能修改前一個(gè)謎題(謎題68)中的X和C這兩個(gè)類。你能否編寫一個(gè)類,其main方法將讀取X.Y類中的Z域的值,然后打印它。注意,不能使用反射。
本謎題初看起來(lái)是不可能實(shí)現(xiàn)的。畢竟,X.Y類被具有相同名字的一個(gè)域給遮掩了,因此對(duì)其命名的嘗試將引用到該域上。
事實(shí)上,我們是可以引用到一個(gè)被遮掩的類型名的,其技巧就是在某一種特殊的語(yǔ)法上下文環(huán)境中使用該名字,在該語(yǔ)法上下文環(huán)境中允許出現(xiàn)一個(gè)類型但是不允許出現(xiàn)一個(gè)變量。在轉(zhuǎn)型表達(dá)式的括號(hào)中間的部分就是這樣一種上下文環(huán)境。下面的程序通過(guò)使用這種技術(shù)解決了這個(gè)謎題,并且將打印出我們所期望的Black:
public class FadeToBlack {
public static void main(String[] args){
System.out.println(((X.Y)null).Z);
}
}
請(qǐng)注意,我們是用一個(gè)具有X.Y類型的表達(dá)式來(lái)訪問(wèn)X.Y類的Z域的。就像我們?cè)谥i題48和54中所看到的,用一個(gè)表達(dá)式而不是類型名來(lái)訪問(wèn)一個(gè)靜態(tài)成員是合法的,但卻是一種有問(wèn)題的用法。
不借助這種有問(wèn)題的用法,而是通過(guò)在一個(gè)類聲明的extends子句中使用一個(gè)被遮掩的類這種方式,你也可以解決本謎題。因?yàn)榛惪偸且环N類型,出現(xiàn)在extends子句中的名字從來(lái)都不會(huì)被解析為變量名。下面的程序就展示了這項(xiàng)技術(shù),它也會(huì)打印出Black:
public class FadeToBlack {
static class Xy extends X.Y{ }
public static void main(String[ ] args){
System.out.println(Xy.Z);
}
}
如果你使用的5.0或更新的版本,那么通過(guò)在一個(gè)類型變量聲明的extends子句中使用X.Y這種方式,你也可以解決本謎題:
public class FadeToBlack {
public static void main(String[] args){
System.out.println(T.Z);
}
}
總之,要解決由類型被變量遮掩而引發(fā)的問(wèn)題,需要按照標(biāo)準(zhǔn)的命名習(xí)慣來(lái)重命名類型和變量,就像在謎題68中所討論的那樣。如果做不到這一點(diǎn),那么你應(yīng)該在只允許類型名的上下文環(huán)境中使用被遮掩的類型名。幸運(yùn)的話,你將永遠(yuǎn)不需要憑借這種對(duì)程序的變形來(lái)解決問(wèn)題,因?yàn)榇蠖鄶?shù)的類庫(kù)作者都很明智,他們都避免了必需使用這種變形的有問(wèn)題的用法。然而,如果你確實(shí)發(fā)現(xiàn)自己身處這種境地,那么你是要了解這個(gè)問(wèn)題需要解決。
本謎題初看起來(lái)是不可能實(shí)現(xiàn)的。畢竟,X.Y類被具有相同名字的一個(gè)域給遮掩了,因此對(duì)其命名的嘗試將引用到該域上。
事實(shí)上,我們是可以引用到一個(gè)被遮掩的類型名的,其技巧就是在某一種特殊的語(yǔ)法上下文環(huán)境中使用該名字,在該語(yǔ)法上下文環(huán)境中允許出現(xiàn)一個(gè)類型但是不允許出現(xiàn)一個(gè)變量。在轉(zhuǎn)型表達(dá)式的括號(hào)中間的部分就是這樣一種上下文環(huán)境。下面的程序通過(guò)使用這種技術(shù)解決了這個(gè)謎題,并且將打印出我們所期望的Black:
public class FadeToBlack {
public static void main(String[] args){
System.out.println(((X.Y)null).Z);
}
}
請(qǐng)注意,我們是用一個(gè)具有X.Y類型的表達(dá)式來(lái)訪問(wèn)X.Y類的Z域的。就像我們?cè)谥i題48和54中所看到的,用一個(gè)表達(dá)式而不是類型名來(lái)訪問(wèn)一個(gè)靜態(tài)成員是合法的,但卻是一種有問(wèn)題的用法。
不借助這種有問(wèn)題的用法,而是通過(guò)在一個(gè)類聲明的extends子句中使用一個(gè)被遮掩的類這種方式,你也可以解決本謎題。因?yàn)榛惪偸且环N類型,出現(xiàn)在extends子句中的名字從來(lái)都不會(huì)被解析為變量名。下面的程序就展示了這項(xiàng)技術(shù),它也會(huì)打印出Black:
public class FadeToBlack {
static class Xy extends X.Y{ }
public static void main(String[ ] args){
System.out.println(Xy.Z);
}
}
如果你使用的5.0或更新的版本,那么通過(guò)在一個(gè)類型變量聲明的extends子句中使用X.Y這種方式,你也可以解決本謎題:
public class FadeToBlack {
public static
System.out.println(T.Z);
}
}
總之,要解決由類型被變量遮掩而引發(fā)的問(wèn)題,需要按照標(biāo)準(zhǔn)的命名習(xí)慣來(lái)重命名類型和變量,就像在謎題68中所討論的那樣。如果做不到這一點(diǎn),那么你應(yīng)該在只允許類型名的上下文環(huán)境中使用被遮掩的類型名。幸運(yùn)的話,你將永遠(yuǎn)不需要憑借這種對(duì)程序的變形來(lái)解決問(wèn)題,因?yàn)榇蠖鄶?shù)的類庫(kù)作者都很明智,他們都避免了必需使用這種變形的有問(wèn)題的用法。然而,如果你確實(shí)發(fā)現(xiàn)自己身處這種境地,那么你是要了解這個(gè)問(wèn)題需要解決。

