乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java Puzzlers(5)更多類之謎...

       ShangShujie 2007-05-03

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

      1。首先來看看一個(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,可很抱歉,此程序是無法編譯通過,剛一看錯(cuò)誤信息你可能愣住:

      無權(quán)訪問private的className。。。

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

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

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

       

      2。也許哪一天你突然想自己寫一個(gè)String來代替java.lang中的String,讓我們來看看會發(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;
          }
      }
      試運(yùn)行此程序,JVM會給你一個(gè)非常奇怪的消息:

      StrungOut dose not have a main method!

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

      3。遮掩(obscure):我覺的翻譯成模糊也許更好。看看下面的例子:

      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";
      }

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

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

      System.out.println(((X.Y)null).Z);   //借助表達(dá)式訪問類變量,還記的嗎?

      在JDK5中還可以這樣:

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

                  System.out.println(T.Z);

       }   

       

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

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

      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è)例子表面上看起來很正常,可事實(shí)上是無法編譯通過的,編譯器告訴我們,找不到恰當(dāng)?shù)膖oString()方法。這是為何?我們明明已經(jīng)導(dǎo)入了 Arrays.toString方法了?。繎?yīng)該打印:[1,2,3,4,5]才對!這是因?yàn)榫幾g器將首先在類ImportDuty的范圍內(nèi)尋找 toString方法,這個(gè)方法將從Object類繼承而來的toString()方法,它并不能接受參數(shù)Object []args!這就是原因所在,某個(gè)范圍內(nèi)的成員對比于靜態(tài)導(dǎo)入的具有優(yōu)先權(quán)。也就是類ImportDuty的toString()方法遮蔽了Arrays.toString(Object []args)方法。遮蔽與遮掩的區(qū)別在于,遮蔽的只能是同類型的名稱,而遮掩的是不同類型的(如變量名遮掩類名,類名遮掩包名)。慎重使用靜態(tài)導(dǎo)入。

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

      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ā)現(xiàn)了嗎?在jdk1.4及以前版本當(dāng)中,此程序無法通過,報(bào)錯(cuò):

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

      說什么第2個(gè)操作數(shù)和第3個(gè)操作數(shù)都不是另外一個(gè)子類。而在JDK5下這個(gè)程序?qū)⒄_\(yùn)行,隨機(jī)打印heads或者tails。這是因?yàn)樵贘DK5以前,條件運(yùn)算符要求:當(dāng)?shù)?個(gè)和第3個(gè)操作數(shù)是引用類型時(shí),它們其中的一個(gè)必須是另外一個(gè)的子類。而例子中Heads和Tails都不是對方的子類,所以產(chǎn)生了上面的錯(cuò)誤。而在JDK5中,這個(gè)條件放寬了,第2個(gè)和第3個(gè)操作數(shù)如果是引用那么都是合法的,只不過其結(jié)果類型將是這兩種類型的最小公共超類。此例中Heads和Tails的超類向上追溯有CoinSide,Object,而CoinSide是他們的最小公共超類。

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

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

      另外一些謎題討論了對Object類中方法的覆寫問題,特別要注意不要覆寫變成了重載



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

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多