Java進階——super關鍵字

腦袋不靈光的小白羊發表於2020-11-15

1 super是一個關鍵字,全部小寫

2 super和this對比著學習

this:

  • this能出現在例項方法和構造方法中

  • this的語法是:“this.”、“this()”

  • this不能使用在靜態方法中

  • this.大部分情況下是可以省略的

  • this.什麼時候不能省略呢?在區分區域性變數和例項變數的時候不能省略

    public void setName(String name){
    this.name = name;
    }

  • this()只能出現在構造方法第一行,通過當前的構造方法去呼叫“本類”中其他的構造方法,目的是:程式碼複用

super:

  • super能出現在例項方法和構造方法中
  • super的語法是:”super.“、”super()“
  • super不能使用在靜態方法中
  • super.大部分情況下是可以省略的
  • super.什麼時候不能省略?
  • super只能出現在構造方法第一行,通過當前的構造方法去呼叫”父類“中的構造方法,目的是:建立子類物件的時候,先初始化父型別特徵。

3 super()
表示通過子類的構造方法呼叫父類的構造方法
模擬現實世界中這種場景,想要有兒子,需要先有父親

4 重要的結論:
當一個構造方法第一行:
既沒有this()又沒有super()的話,預設會有一個super();
表示通過當前子類的構造方法呼叫父類的無引數構造方法
所以必須保證父類的無引數構造方法是存在的

5 注意:
this()和super()不能共存,它們都是隻能出現在構造方法的第一行

6 無論是怎樣折騰,父類的構造方法是一定會執行的(百分比的)

public class SuperTest01{
	public static void main(String[] args){
		// 建立子類物件
		/*
			A類的無引數構造方法!
			B類的無引數構造方法!
		*/
		new B();
	}
}

class A extends Object{

	// 建議手動的將一個類的無引數構造方法寫出來。
	public A(){
		//super(); // 這裡也是預設有這一行程式碼的。
		System.out.println("A類的無引數構造方法!");
	}

	// 一個類如果沒有手動提供任何構造方法,系統會預設提供一個無引數構造方法。
	// 一個類如果手動提供了一個構造方法,那麼無引數構造系統將不再提供。
	public A(int i){
		//super();
		System.out.println("A類的有引數構造方法(int)");
	}
}

class B extends A{
	/*
	public B(){
		super();
		System.out.println("B類的無引數構造方法!");
	}
	*/

	public B(){
		this("zhangsan");
		// 呼叫父類中有引數的構造方法
		//super(123);
		System.out.println("B類的無引數構造方法!");
	}

	public B(String name){
		super();
		System.out.println("B類的有引數構造方法(String)");
	}
}

判斷程式的輸出結果
1
3
6
5
4
在java語言中不管是new什麼物件,最後老祖宗的Object類的無參構造方法一定會執行。(Object類的的無引數構造方法是處於”棧頂部“)

棧頂的特點:
最後呼叫,但是最先執行結束
後進先出原則

大家要注意:
以後寫程式碼的時候,一個類的無引數構造方法還是建議大家手動的寫出來
如果無引數構造方法丟失的話,可能會影響到”子類物件的構建“

	public static void main(String[] args){
		new C();

	}
}

/*
class Object{
	public Object(){	
	}
}
*/

class A extends Object{
	public A(){
		System.out.println("1"); //1
	}
}

class B extends A{
	public B(){
		System.out.println("2"); //2
	}
	public B(String name){
		super();
		System.out.println("3"); // 3
	}
}

class C extends B{
	public C(){ // 這個是最先呼叫的。但是最後結束。
		this("zhangsan");
		System.out.println("4");//4
	}
	public C(String name){
		this(name, 20);
		System.out.println("5");//5
	}
	public C(String name, int age){
		super(name);
		System.out.println("6");//6
	}
}
  • 舉個例子:在恰當的時間使用:super(實際引數列表);

  • 注意:在構造方法執行過程中一連串呼叫了父類的構造方法,父類的構造方法又繼續向下呼叫它的父類的構造方法,但是實際上物件只建立了一個

  • 思考:”super(實參)“到底是幹啥的?
    super(實參)的作用是:初始化當前物件的父型別特證
    並不是建立物件,實際上物件只建立了1個

  • super關鍵字代表什麼呀?

    super關鍵字代表的就是”當前物件“的那部分父型別特徵

    我繼承了我父親的一部分特徵:
    例如:眼睛、皮膚等。
    super代表的就是”眼睛、皮膚等“。
    ”眼睛、皮膚等“雖然是繼承了父親的,但這部分是在我身上呢。

// 測試程式
public class SuperTest03{
	public static void main(String[] args){

		CreditAccount ca1 = new CreditAccount();
		System.out.println(ca1.getActno() + "," + ca1.getBalance() + "," + ca1.getCredit());

		CreditAccount ca2 = new CreditAccount("1111", 10000.0, 0.999);
		System.out.println(ca2.getActno() + "," + ca2.getBalance() + "," + ca2.getCredit());

	}
}

// 賬戶
class Account extends Object{
	// 屬性
	private String actno;
	private double balance;

	// 構造方法
	public Account(){
		//super();
		//this.actno = null;
		//this.balance = 0.0;
	}
	public Account(String actno, double balance){
		// super();
		this.actno = actno;
		this.balance = balance;
	}

	// setter and getter
	public void setActno(String actno){
		this.actno = actno;
	}
	public String getActno(){
		return actno;
	}
	public void setBalance(double balance){
		this.balance = balance;
	}
	public double getBalance(){
		return balance;
	}
}

// 信用賬戶
class CreditAccount extends Account{

	// 屬性:信譽度(誠信值)
	// 子類特有的一個特徵,父類沒有。
	private double credit;

	// 構造方法
	// 分析以下程式是否存在編譯錯誤????
	public CreditAccount(String actno, double balance, double credit){

		// 私有的屬性,只能在本類中訪問。
		/*
		this.actno = actno;
		this.balance = balance;
		*/

		// 以上兩行程式碼在恰當的位置,正好可以使用:super(actno, balance);
		// 通過子類的構造方法呼叫父類的構造方法。
		super(actno, balance);
		this.credit = credit;
	}

	// 提供有引數的構造方法
	public CreditAccount(){
		//super();
		//this.credit = 0.0;
	}

	// setter and getter方法
	public void setCredit(double credit){
		this.credit = credit;
	}
	public double getCredit(){
		return credit;
	}
	
}

super的原理
在這裡插入圖片描述

public class SuperTest04{
	public static void main(String[] args){
		Vip v = new Vip("張三");
		v.shopping();
	}
}
class Customer{
	String name;
	public Customer(){}
	public Customer(String name){
		super();
		this.name = name;
	}
}
class Vip extends Customer{
	public Vip(){}
	public Vip(String name){
		super(name);
	}
	// super和this都不能出現在靜態方法中。
	public void shopping(){
		// this表示當前物件。
		System.out.println(this.name + "正在購物!");
		// super表示的是當前物件的父型別特徵。(super是this指向的那個物件中的一塊空間。)
		System.out.println(super.name + "正在購物!");
		System.out.println(name + "正在購物!");
	}
}

super關鍵字的理解
在這裡插入圖片描述

1、“this.”和“super.”大部分情況下都是可以省略的。

2、this. 什麼時候不能省略?
	public void setName(String name){
		this.name = name;
	}
3、super. 什麼時候不能省略?
	父中有,子中又有,如果想在子中訪問“父的特徵”,super. 不能省略。
public class SuperTest05{
	public static void main(String[] args){
		Vip v = new Vip("張三");
		v.shopping();
	}
}
class Customer {
	String name;
	public Customer(){}
	public Customer(String name){
		super();
		this.name = name;
	}

	public void doSome(){
		System.out.println(this.name + " do some!");
		System.out.println(name + " do some!");
		//錯誤: 找不到符號
		//System.out.println(super.name + " do some!");
	}
}
class Vip extends Customer{

	// 假設子類也有一個同名屬性
	// java中允許在子類中出現和父類一樣的同名變數/同名屬性。
	String name; // 例項變數

	public Vip(){
	}
	public Vip(String name){
		super(name);
		// this.name = null;
	}
	public void shopping(){
		/*
			java是怎麼來區分子類和父類的同名屬性的?
				this.name:當前物件的name屬性
				super.name:當前物件的父型別特徵中的name屬性。
		*/
		System.out.println(this.name + "正在購物!"); // null 正在購物
		System.out.println(super.name + "正在購物!"); // 張三正在購物
		System.out.println(name + "正在購物!"); //null 正在購物
	}
}

superTest05記憶體圖
在這裡插入圖片描述

通過以下這個測試得出結論:

super不是引用。super也不不儲存記憶體地址,super也不指向任何物件

super只是代表當前內部的那一塊父型別的特徵

public class SuperTest06 {

	// 例項方法
	public void doSome(){
		// SuperTest06@2f92e0f4
		System.out.println(this);
		// 輸出“引用”的時候,會自動呼叫引用的toString()方法。
		//System.out.println(this.toString());

		//編譯錯誤: 需要'.'
		//System.out.println(super);
	}

	// this和super不能使用在static靜態方法中。
	/*
	public static void doOther(){
		System.out.println(this);
		System.out.println(super.xxx);
	}
	*/

	// 靜態方法,主方法
	public static void main(String[] args){
		SuperTest06 st = new SuperTest06();
		st.doSome();

		// main方法是靜態的
		// 錯誤的。
		/*
		System.out.println(this);
		System.out.println(super.xxxx);
		*/
	}
}

在父和子中有同名的屬性,或者說有相同的方法

如果此時想在子類中訪問父中的資料,必須使用”super.“加以區分

super.屬性名【訪問父類的屬性】
super.方法名(實參)【訪問父類的方法】
super(實參)【呼叫父類的構造方法】

public class SuperTest07{
	public static void main(String[] args){
		/*
			Cat move!
			Cat move!
			Animal move!
		*/
		Cat c = new Cat();
		c.yiDong();
	}
}

class Animal{
	public void move(){
		System.out.println("Animal move!");
	}
}

class Cat extends Animal{
	// 對move進行重寫。
	public void move(){
		System.out.println("Cat move!");
	}

	// 單獨編寫一個子類特有的方法。
	public void yiDong(){
		this.move();
		move();
		// super. 不僅可以訪問屬性,也可以訪問方法。
		super.move();
	}
}

重點以及結論

			super的用法:super. 和 super()

			super. 大部分可以省略,當父子都有相同的屬性和方法時,
			在子類中訪問父類的特徵時,必須使用super.

			一個構造方法第一行啥也沒有,自動會有一個super()

			super不能出現在靜態方法中,只能是例項方法。

			super()是幹啥的:是通過子類的構造方法呼叫父類的構造方法。

相關文章