gdufo

           

          JAVA面試題解惑系列(三)——變量(屬性)的覆蓋

          http://www.javaeye.com/topic/211281
          變量,或者叫做類(lèi)的屬性,在繼承的情況下,如果父類(lèi)和子類(lèi)存在同名的變量會(huì)出現(xiàn)什么情況呢?這一次,我們就一起來(lái)回顧一下這個(gè)問(wèn)題——變量(屬性)的覆蓋。

          這個(gè)問(wèn)題雖然簡(jiǎn)單,但是情況卻比較復(fù)雜。因?yàn)槲覀儾粌H要考慮變量、靜態(tài)變量和常量三種情況,還要考慮private、friendly(即不加訪問(wèn)修飾符)、protected和public四種訪問(wèn)權(quán)限下對(duì)屬性的不同影響。

          我們先從普通變量說(shuō)起。依照我們的慣例,先來(lái)看一段代碼:
           1class ParentClass {   
           2    private String privateField = "父類(lèi)變量--private";   
           3  
           4    /* friendly */String friendlyField = "父類(lèi)變量--friendly";   
           5  
           6    protected String protectedField = "父類(lèi)變量--protected";   
           7  
           8    public String publicField = "父類(lèi)變量--public";   
           9  
          10    // private的變量無(wú)法直接訪問(wèn),因此我們給他增加了一個(gè)訪問(wèn)方法   
          11    public String getPrivateFieldValue() {   
          12        return privateField;   
          13    }
             
          14}
             
          15  
          16public class SubClass extends ParentClass {   
          17    private String privateField = "子類(lèi)變量--private";   
          18  
          19    /* friendly */String friendlyField = "子類(lèi)變量--friendly";   
          20  
          21    protected String protectedField = "子類(lèi)變量--protected";   
          22  
          23    public String publicField = "子類(lèi)變量--public";   
          24  
          25    // private的變量無(wú)法直接訪問(wèn),因此我們給他增加了一個(gè)訪問(wèn)方法   
          26    public String getPrivateFieldValue() {   
          27        return privateField;   
          28    }
             
          29  
          30    public static void main(String[] args) {   
          31        // 為了便于查閱,我們統(tǒng)一按照private、friendly、protected、public的順序   
          32        // 輸出下列三種情況中變量的值   
          33  
          34        // ParentClass類(lèi)型,ParentClass對(duì)象   
          35        ParentClass parentClass = new ParentClass();   
          36        System.out.println("ParentClass parentClass = new ParentClass();");   
          37        System.out.println(parentClass.getPrivateFieldValue());   
          38        System.out.println(parentClass.friendlyField);   
          39        System.out.println(parentClass.protectedField);   
          40        System.out.println(parentClass.publicField);   
          41  
          42        System.out.println();   
          43  
          44        // ParentClass類(lèi)型,SubClass對(duì)象   
          45        ParentClass subClass = new SubClass();   
          46        System.out.println("ParentClass subClass = new SubClass();");   
          47        System.out.println(subClass.getPrivateFieldValue());   
          48        System.out.println(subClass.friendlyField);   
          49        System.out.println(subClass.protectedField);   
          50        System.out.println(subClass.publicField);   
          51  
          52        System.out.println();   
          53  
          54        // SubClass類(lèi)型,SubClass對(duì)象   
          55        SubClass subClazz = new SubClass();   
          56        System.out.println("SubClass subClazz = new SubClass();");   
          57        System.out.println(subClazz.getPrivateFieldValue());   
          58        System.out.println(subClazz.friendlyField);   
          59        System.out.println(subClazz.protectedField);   
          60        System.out.println(subClazz.publicField);   
          61    }
             
          62}
            
          63

          這段代碼的運(yùn)行結(jié)果如下:

          1. ParentClass parentClass = new ParentClass();
          2. 父類(lèi)變量--private
          3. 父類(lèi)變量--friendly
          4. 父類(lèi)變量--protected
          5. 父類(lèi)變量--public
          6. ParentClass subClass = new SubClass();
          7. 子類(lèi)變量--private
          8. 父類(lèi)變量--friendly
          9. 父類(lèi)變量--protected
          10. 父類(lèi)變量--public
          11. SubClass subClazz = new SubClass();
          12. 子類(lèi)變量--private
          13. 子類(lèi)變量--friendly
          14. 子類(lèi)變量--protected
          15. 子類(lèi)變量--public


          從上面的結(jié)果中可以看出,private的變量與其它三種訪問(wèn)權(quán)限變量的不同,這是由于方法的重寫(xiě)(override)而引起的。關(guān)于重寫(xiě)知識(shí)的回顧留給以后的章節(jié),這里我們來(lái)看一下其它三種訪問(wèn)權(quán)限下變量的覆蓋情況。

          分析上面的輸出結(jié)果就會(huì)發(fā)現(xiàn),變量的值取決于我們定義的變量的類(lèi)型,而不是創(chuàng)建的對(duì)象的類(lèi)型。

          在上面的例子中,同名的變量訪問(wèn)權(quán)限也是相同的,那么對(duì)于名稱相同但是訪問(wèn)權(quán)限不同的變量,情況又會(huì)怎樣呢?事實(shí)勝于雄辯,我們繼續(xù)來(lái)做測(cè)試。由于private變量的特殊性,在接下來(lái)的實(shí)驗(yàn)中我們都把它排除在外,不予考慮。

          由于上面的例子已經(jīng)說(shuō)明了,當(dāng)變量類(lèi)型是父類(lèi)(ParentClass)時(shí),不管我們創(chuàng)建的對(duì)象是父類(lèi)(ParentClass)的還是子類(lèi)(SubClass)的,都不存在屬性覆蓋的問(wèn)題,因此接下來(lái)我們也只考慮變量類(lèi)型和創(chuàng)建對(duì)象都是子類(lèi)(SubClass)的情況

          class ParentClass {   
              
          /* friendly */String field = "父類(lèi)變量";   
          }
             
            
          public class SubClass extends ParentClass {   
              
          protected String field = "子類(lèi)變量";   
            
              
          public static void main(String[] args) {   
                  SubClass subClass 
          = new SubClass();   
                  System.out.println(subClass.field);   
              }
             
          }
            

          運(yùn)行結(jié)果:
            子類(lèi)變量

          class ParentClass {   
              
          public String field = "父類(lèi)變量";   
          }
             
            
          public class SubClass extends ParentClass {   
              
          protected String field = "子類(lèi)變量";   
            
              
          public static void main(String[] args) {   
                  SubClass subClass 
          = new SubClass();   
                  System.out.println(subClass.field);   
              }
             
          }
            

          上面兩段不同的代碼,輸出結(jié)果確是相同的。事實(shí)上,我們可以將父類(lèi)和子類(lèi)屬性前的訪問(wèn)修飾符在friendly、protected和public之間任意切換,得到的結(jié)果都是相同的。也就是說(shuō)訪問(wèn)修飾符并不影響屬性的覆蓋,關(guān)于這一點(diǎn)大家可以自行編寫(xiě)測(cè)試代碼驗(yàn)證。

          對(duì)于靜態(tài)變量和常量又會(huì)怎樣呢?我們繼續(xù)來(lái)看

          class ParentClass {   
              
          public static String staticField = "父類(lèi)靜態(tài)變量";   
            
              
          public final String finalField = "父類(lèi)常量";   
            
              
          public static final String staticFinalField = "父類(lèi)靜態(tài)常量";   
          }
             
            
          public class SubClass extends ParentClass {   
              
          public static String staticField = "子類(lèi)靜態(tài)變量";   
            
              
          public final String finalField = "子類(lèi)常量";   
            
              
          public static final String staticFinalField = "子類(lèi)靜態(tài)常量";   
            
              
          public static void main(String[] args) {   
                  SubClass subClass 
          = new SubClass();   
                  System.out.println(SubClass.staticField);   
                  System.out.println(subClass.finalField);   
                  System.out.println(SubClass.staticFinalField);   
              }
             
          }
            
          運(yùn)行結(jié)果如下:
          1. 子類(lèi)靜態(tài)變量
          2. 子類(lèi)常量
          3. 子類(lèi)靜態(tài)常量

          雖然上面的結(jié)果中包含“子類(lèi)靜態(tài)變量”和“子類(lèi)靜態(tài)常量”,但這并不表示父類(lèi)的“靜態(tài)變量”和“靜態(tài)常量”可以被子類(lèi)覆蓋,因?yàn)樗鼈兌际菍儆陬?lèi),而不屬于對(duì)象。

          上面的例子中,我們一直用對(duì)象來(lái)對(duì)變量(屬性)的覆蓋做測(cè)試,如果是基本類(lèi)型的變量,結(jié)果是否會(huì)相同呢?答案是肯定的,這里我們就不再一一舉例說(shuō)明了。

          最后,我們來(lái)做個(gè)總結(jié)。通過(guò)以上測(cè)試,可以得出一下結(jié)論:
          1. 由于private變量受訪問(wèn)權(quán)限的限制,它不能被覆蓋。
          2. 屬性的值取父類(lèi)還是子類(lèi)并不取決于我們創(chuàng)建對(duì)象的類(lèi)型,而是取決于我們定義的變量的類(lèi)型。
          3. friendly、protected和public修飾符并不影響屬性的覆蓋。
          4. 靜態(tài)變量和靜態(tài)常量屬于類(lèi),不屬于對(duì)象,因此它們不能被覆蓋。
          5. 常量可以被覆蓋。
          6. 對(duì)于基本類(lèi)型和對(duì)象,它們適用同樣的覆蓋規(guī)律。

          posted on 2008-08-22 13:07 gdufo 閱讀(246) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVA 基礎(chǔ)

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(6)

          隨筆分類(lèi)

          隨筆檔案

          文章分類(lèi)

          文章檔案

          收藏夾

          Hibernate

          友情鏈接

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 监利县| 富川| 当涂县| 财经| 平泉县| 都匀市| 东山县| 沈阳市| 绍兴县| 延川县| 灌云县| 当雄县| 唐山市| 集安市| 夹江县| 佛学| 亳州市| 兴山县| 罗山县| 台南县| 定州市| 清流县| 托克逊县| 疏附县| 昌吉市| 商城县| 崇明县| 伊金霍洛旗| 永吉县| 望奎县| 岳阳县| 内乡县| 乌什县| 民权县| 阳城县| 平远县| 沈阳市| 安宁市| 库伦旗| 衡阳县| 平乐县|