1.第一種用法主要用來在子類中調用父類的同名成員變量或者方法
測試如下:
//
class A{
public String name="孫悟空";
public void testSuper(){
System.out.println("父類");
}
}
public class B extends A{
public String name="豬八戒";
public int age;
public void testSuper() {
System.out.println("子類");
}
public void test(){
System.out.println(name);//調用子類的成員變量
System.out.println(super.name);//調用父類的成員變量
testSuper();//調用子類的方法
super.testSuper();//調用父類的方法
}
public static void main(String[] args) {
B b=new B();
b.test();
}
}
內存分析:
分析任何程序都是從main方法的第一句開始分析的,所以首先分析main方法裏面的第一句話:
//
B b=new B();
程序執行到這裏時,首先在棧空間裏面會產生一個對象地址,通過這個值我們可以找到new出來的b對象。由於子類B是從父類A繼承下來的,所以當我們new一個子類對象的時候,這個子類對象裏面會包含有一個父類對象,而這個父類對象擁有他自身的屬性name。這個name成員變量在A類裏面聲明的時候初始化爲孫悟空。
子類在繼承父類name屬性的同時,自己也單獨定義了一個name屬性,所以當我們new出一個子類對象的時候,這個對象會有兩個name屬性,一個是從父類繼承下來的name,另一個是自己的name。在子類裏定義的成員變量value在聲明時初始化爲豬八戒。因此,執行完第一句話以後,系統內存的佈局如下圖所示:
2.第二種主要用在子類的構造器中顯示地調用父類的構造器,要注意的是,如果是用在子類構造器中,則必須是子類構造器的第一個語句。
//
class A{
public String name="孫悟空";
public A(){
}
public A(String name) {
this.name = name;
}
}
public class B extends A{
public String name="豬八戒";
public int age;
public B() {
}
public B(String name, int age) {
super(name); //在構造函數裏面使用super調用父類構造器進行初始化,必須是構造函數的第一行代碼
this.age = age;
}
public static void main(String[] args) {
B b = new B();
}
}
當new一個對象出來的時候,這個對象會產生一個this的引用,這個this引用指向對象自身。如果new出來的對象是一個子類對象的話,那麼這個子類對象裏面還會有一個super引用,這個super指向當前對象裏面的父對象。所以相當於程序裏面有一個this,this指向對象自己,還有一個super,super指向當前對象裏面的父對象。
3.super不能在靜態方法裏面使用,因爲靜態方法屬於類,但是super是屬於對象的。super 可以調用的是父類的成員函數(即非靜態的)和成員變量(即非靜態的),需要調用父類的類函數和類變量則需要用父類名調用.
測試:
//
class A{
public static String name="孫悟空";
public static void testSuper1(){
System.out.println("父類1");
}
public void testSuper3() {
System.out.println("父類2");
}
}
public class B extends A{
public String name="豬八戒";
public int age;
public void testSuper2() {
System.out.println("子類");
super.name; //Not a statement
}
public static void main(String[] args) {
B b=new B();
super.testSuper2();//super' cannot be referenced from a static context
}
}