欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java Puzzlers(5)更多類(lèi)之謎

本章更多討論了子類(lèi)對父類(lèi)的繼承可能導致的各種陷阱,比如隱藏(hidden),遮蔽(shadow),遮掩(obscure),覆寫(xiě)(override),重載(overload)等行為。

1。首先來(lái)看看一個(gè)隱藏的例子:

class Base {
    public String className = "Base";
}

class Derived extends Base {
    private String className = "Derived";
}

public class PrivateMatter {
    public static void main(String[] args) {
        System.out.println(new Derived().className);
    }
}

我們可能指望它打印Base,可很抱歉,此程序是無(wú)法編譯通過(guò),剛一看錯誤信息你可能愣?。?/p>

無(wú)權訪(fǎng)問(wèn)private的className。。。

對于實(shí)例方法,子類(lèi)可以對父類(lèi)的實(shí)例方法進(jìn)行覆寫(xiě),可對于實(shí)例變量(而且包括類(lèi)變量,靜態(tài)方法,final靜態(tài)變量),子類(lèi)只能隱藏父類(lèi)中的相同名稱(chēng)的變量,而不是覆寫(xiě)。根據newDerived()的編譯期類(lèi)型為子類(lèi)Derived,調用子類(lèi)的className屬性,可此屬性是聲明為private的,所以無(wú)法編譯通過(guò)。如果我們想調用父類(lèi)中被隱藏的className,可以通過(guò)向上轉型來(lái)實(shí)現:

System.out.println(((Base)new Derived()).className);

此例告訴我們,JAVA語(yǔ)言中子類(lèi)定義與父類(lèi)相同類(lèi)型和名稱(chēng)的變量、嵌套類(lèi)型和靜態(tài)方法,都將隱藏掉父類(lèi)中相應的方法,而不是覆寫(xiě),所以,請避免隱藏!此過(guò)程中當然也不存在所謂多態(tài)。另外,我們不應該違反這樣一條規則:對基類(lèi)所做的任何行為,都應當可以同樣作用于子類(lèi)。此例中子類(lèi)className為private,違反了基類(lèi)中className是public的定義,這樣的寫(xiě)法應該避免。

 

2。也許哪一天你突然想自己寫(xiě)一個(gè)String來(lái)代替java.lang中的String,讓我們來(lái)看看會(huì )發(fā)生什么?

public class StrungOut {
    public static void main(String[] args) {
        String s = new String("Hello world");
        System.out.println(s);
    }
}

class String {
    private final java.lang.String s;

    public String(java.lang.String s) {
        this.s = s;
    }

    public java.lang.String toString() {
        return s;
    }
}
試運行此程序,JVM會(huì )給你一個(gè)非常奇怪的消息:

StrungOut dose not have a main method!

怪了,明明有個(gè)main方法????請注意,main方法中的參數String []args,其中的String類(lèi)型要求是java.lang.String,可JVM會(huì )自動(dòng)地把把這些參數認為是我們自定義的下面那個(gè)String類(lèi)型,這就是錯誤的原因所在。教訓:避免重用類(lèi)名,特別是java平臺的類(lèi)型,特別是java.lang包下的類(lèi)名!在此例中,當前類(lèi)所在包中的所有類(lèi)的main方法都將因此失效。

3。遮掩(obscure):我覺(jué)的翻譯成模糊也許更好??纯聪旅娴睦樱?/p>

public class ShadesOfGray {
    public static void main(String[] args){
        System.out.println(X.Y.Z);
    }
}

class X {
    static class Y {
        static String Z = "Black";
    }

    static C Y = new C();
}

class C {
    String Z = "White";
}

你認為他應該打印什么呢??黑還是白?還是黑白不分:),光明的力量總是偉大,它一直打印的是:white。這說(shuō)明了X.Y一直調用的是靜態(tài)變量Y,而不是靜態(tài)內隱類(lèi)Y。JAVA語(yǔ)言規范告訴我們,當一個(gè)變量和一個(gè)類(lèi)型具有相同的名字,明確他們位于相同的作用范圍內,變量名具有優(yōu)先權,同樣,變量名與類(lèi)型名將遮掩包名。

即變量名>類(lèi)型名>包名。其實(shí)上面的例子有更嚴重的問(wèn)題,它并沒(méi)有遵循標準的JAVA命名習慣,變量應該以小寫(xiě)開(kāi)頭(mixedCase的格式),類(lèi)名以大寫(xiě)開(kāi)頭(MaxedCase的格式),如果完全遵照習慣來(lái)寫(xiě),就不會(huì )出現此問(wèn)題了。所以,請遵守標準的命名習慣。退一步,假設在某些情況下我們只能以此方式書(shū)寫(xiě),那我們怎么訪(fǎng)問(wèn)靜態(tài)內隱類(lèi)Y呢??jì)煞N方法:

System.out.println(((X.Y)null).Z);   //借助表達式訪(fǎng)問(wèn)類(lèi)變量,還記的嗎?

在JDK5中還可以這樣:

public static <T extends X.Y> void main(String args[]){     //繼承X.Y類(lèi)解決此問(wèn)題。

            System.out.println(T.Z);

 }   

 

4。包A中的某個(gè)類(lèi)被另一個(gè)包C中的子類(lèi)所繼承,如果子類(lèi)當中“覆寫(xiě)”了父類(lèi)中的方法,而此方法在父類(lèi)中不是聲明為public或者protected,那么這并非覆寫(xiě),這兩個(gè)方法將沒(méi)有任何關(guān)系。所以,如果你希望某個(gè)類(lèi)的一個(gè)方法被包外的子類(lèi)所覆寫(xiě),請把此方法聲明為protected或者public。

5。遮蔽(shadow),這里討論了JDK5靜態(tài)導入需要注意的問(wèn)題,看下面的例子:

import static java.util.Arrays.toString;

class ImportDuty {
    public static void main(String[] args) {
        printArgs(1, 2, 3, 4, 5);
    }

    static void printArgs(Object... args) {
        System.out.println(toString(args));
    }
}
這個(gè)例子表面上看起來(lái)很正常,可事實(shí)上是無(wú)法編譯通過(guò)的,編譯器告訴我們,找不到恰當的toString()方法。這是為何?我們明明已經(jīng)導入了Arrays.toString方法了???應該打印:[1,2,3,4,5]才對!這是因為編譯器將首先在類(lèi)ImportDuty的范圍內尋找toString方法,這個(gè)方法將從Object類(lèi)繼承而來(lái)的toString()方法,它并不能接受參數Object []args!這就是原因所在,某個(gè)范圍內的成員對比于靜態(tài)導入的具有優(yōu)先權。也就是類(lèi)ImportDuty的toString()方法遮蔽了Arrays.toString(Object []args)方法。遮蔽與遮掩的區別在于,遮蔽的只能是同類(lèi)型的名稱(chēng),而遮掩的是不同類(lèi)型的(如變量名遮掩類(lèi)名,類(lèi)名遮掩包名)。慎重使用靜態(tài)導入。

6。最后一個(gè)謎題很重要哦,我現在才知道JDK5對條件操作符(a?b:c)已經(jīng)有重大改變。試著(zhù)分別在JDK1.4和JDK5中運行下面的程序:

import java.util.Random;

public class CoinSide {
    private static Random rnd = new Random();

    public static CoinSide flip() {
        return rnd.nextBoolean() ?
            Heads.INSTANCE : Tails.INSTANCE;
    }

    public static void main(String[] args) {
        System.out.println(flip());
    }
}

class Heads extends CoinSide {
    private Heads() { }
    public static final Heads INSTANCE = new Heads();

    public String toString() {
        return "heads";
    }
}

class Tails extends CoinSide {
    private Tails() { }
    public static final Tails INSTANCE = new Tails();

    public String toString() {
        return "tails";
    }
}
發(fā)現了嗎?在jdk1.4及以前版本當中,此程序無(wú)法通過(guò),報錯:

incompatible types for ?: neither is a subtype of the other

說(shuō)什么第2個(gè)操作數和第3個(gè)操作數都不是另外一個(gè)子類(lèi)。而在JDK5下這個(gè)程序將正常運行,隨機打印heads或者tails。這是因為在JDK5以前,條件運算符要求:當第2個(gè)和第3個(gè)操作數是引用類(lèi)型時(shí),它們其中的一個(gè)必須是另外一個(gè)的子類(lèi)。而例子中Heads和Tails都不是對方的子類(lèi),所以產(chǎn)生了上面的錯誤。而在JDK5中,這個(gè)條件放寬了,第2個(gè)和第3個(gè)操作數如果是引用那么都是合法的,只不過(guò)其結果類(lèi)型將是這兩種類(lèi)型的最小公共超類(lèi)。此例中Heads和Tails的超類(lèi)向上追溯有CoinSide,Object,而CoinSide是他們的最小公共超類(lèi)。

如果想在JDK5以前運行上面的程序,可以把第2或者第3操作數向上轉型為他們的超類(lèi)即可:

   public static CoinSide flip() {
        return rnd.nextBoolean() ?
            (CoinSide)Heads.INSTANCE : Tails.INSTANCE;
    }

另外一些謎題討論了對Object類(lèi)中方法的覆寫(xiě)問(wèn)題,特別要注意不要覆寫(xiě)變成了重載



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=728172

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java接口 詳解(二)
最全的Java筆試題庫之選擇題篇-總共234道【1~60】
Java FAQ(新手必看)
一些JavaSE學(xué)習過(guò)程中的思路整理(一)(主觀(guān)性強,持續更新中...)
java---- 封裝,接口,繼承,覆蓋,構造過(guò)程,多態(tài),static、this、super、final用法
數組
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久