出處:http://renyanwei.iteye.com/blog/258304
我們知道,在JAVA中,子類可以繼承父類,如果子類聲明的方法與父類有重名的情況怎么辦,大伙兒都知道要是重寫,但是實際上這又分為兩種 情況,就是方法和變量在繼承時的覆蓋和隱藏問題,這些概念性的東西看似無聊,但是在面試或者是SCJP認證題中圍繞這些是會經常碰到的,所以這里來討論下
首先我們來看幾個概念
隱藏 :child隱藏了parent的變量和方法,那么,child不能訪問parent被隱藏的變量或者方法,但是,講B轉換成A中,可以訪問A被隱藏的變量或者方法
覆蓋 :child覆蓋了parent的變量或者方法,那么,child不能訪問parent被覆蓋的變量或者方法,將child轉換成parent后同樣不能訪問parent被覆蓋的變量或者方法
首先看一下JAVA中方法和變量在繼承時的覆蓋和隱藏規則
1.父類的實例變量和靜態變量能被子類的同名變量隱藏
2.父類的靜態方法被子類的同名靜態方法隱藏
3.父類的實例方法被子類的同名實例變量覆蓋
還有幾點需要注意的是
1.不能用子類的靜態方法隱藏 父類中同樣標示(也就是返回值 名字 參數都一樣)的實例方法
2.不能用子類的實例方法覆蓋 父類中同樣標示的靜態方法
3.這點兒請注意,就是變量只會被隱藏 不會被覆蓋 ,無論他是實例變量還是靜態變量,而且,子類的靜態變量可以隱藏 父類的實例變量,子類的實例變量可以隱藏 父類的靜態變量
O(∩_∩)O哈哈~ 是不是有點兒繞口,沒關系 我們看一個實例
創建兩個父子類關系的類
- //父類
- class Parent
- {
- public static String kind="javastudy.extendsstudy.parent";
- public static int age=50;
- public String name="Parent";
- //靜態方法,返回包名
- public static String getKind()
- {
- System.out.println("parent的getKind()方法被調用了");
- return kind;
- }
- //靜態方法,返回年齡
- public static int getAge()
- {
- System.out.println("Parent的getAge()方法被調用了");
- return age;
- }
- //實例方法,返回姓名
- public String getName()
- {
- System.out.println("Parent的getName()方法被調用了");
- return this.name;
- }
- }
- //子類
- class Child extends Parent
- {
- public static String kind="javastudy.extendsstudy.child";
- public int age=25;
- public String name="child";
- //隱藏父類靜態方法
- public static String getKind()
- {
- System.out.println("child的getkind()方法被調用了");
- return kind;
- }
- //獲取父類包名
- public static String getParentKind()
- {
- return Parent.kind;
- }
- //覆蓋父類實例方法
- public String getName()
- {
- System.out.println("child的getName()被調用了");
- return this.name;
- }
- //獲取父類名稱
- public String getParentName()
- {
- return super.name;
- }
- /*
- *錯誤,實例方法不能覆蓋父類的靜態方法
- public int getAge()
- {
- return this.age;
- }
- */
- }
然后測試下
- class Test
- {
- public static void main(String[] args)
- {
- Child child=new Child();
- System.out.printf("子類名稱:%s,年齡:%d,包名:%s%n",child.name,child.age,child.kind);
- //輸出:子類名稱:child,年齡:25,包:javastudy.extendsstudy.child
- //把child轉換成parent對象
- Parent parent=child;
- System.out.printf("轉換后的名稱:%s,年齡:%d,包名:%s%n",parent.name,parent.age,parent.kind);
- //輸出:轉換后的名稱:Parent,年齡:50,包:javastudy.extendsstudy.parent
- System.out.printf("子類訪問父類被隱藏的實例變量name:%s%n",child.getParentName());
- //輸出:子類訪問父類被隱藏的實例變量name:Parent
- System.out.printf("子類訪問父類被隱藏的靜態變量kind:%s",child.getParentKind());
- //輸出:子類訪問父類被隱藏的靜態變量kind:javastudy.extendsstudy.parent
- child.getName();
- //輸出:child的getName()被調用了
- //**************注意看這個方法,返回的還是子類的getName
- parent.getName();
- //輸出:child的getName()被調用了
- child.getKind();
- //輸出:child的getkind()方法被調用了
- parent.getKind();
- //輸出:parent的getKind()方法被調用了
- }
- }
好了,看了結果后總結下吧
1.同名的實例方法被覆蓋 ,同名的靜態方法被隱藏 ,child類的getName實例方法覆蓋 了parent的getName實例方法,chind的getKind方法隱藏 了parent類的getKind方法
2.隱藏 和覆蓋 的區別在於,子類對象轉換成父類對象后,能夠訪問父類被隱藏 的變量和方法,而不能訪問父類被覆蓋 的方法
3.如果需要訪問父類被隱藏 的實例變量,加上super就好了,比如訪問父類的name,寫上super.name就好了
本文不是教會大家重寫父類變量的,而是重點說明方法和變量的隱藏和覆蓋,這些個小知識點雖然在做項目的時候不怎么會用到,但是一定要記住,不然的話很多錯誤會感到莫名其妙,還有就是SCJP的題庫里這類題大大存在,所以本人覺得這些細小的知識還是記住為好