文章目錄
一. this引用
1. this引用的介紹
- this引用是成員方法的參數之一,不需要用户傳遞實現,由編譯器自動完成,也就是説,這個參數用户是看不到的,但用户可使用這個參數。
- this引用指向當前對象(成員方法運行時調用該成員方法的對象),在成員方法中所有成員變量的操作,都是通過該引用去訪問。 只不過所有的操作對用户是透明的,即用户不需要來傳遞,編譯器自動完成。
- this 引用的是調用成員方法的對象。
2. this引用的特性
- this的類型:對應類 類型引用,即哪個對象調用就是哪個對象的引用類型
- this只能在"成員方法"中使用
- 在"成員方法"中,this只能引用當前對象,不能再引用其他對象
- this是“成員方法”第一個隱藏的參數,編譯器會自動傳遞,在成員方法執行時, 編譯器會負責將調用成員方法對象的引用傳遞給該成員方法,this負責來接收
- 用户也可以將由編譯器實現的形參this手動給出,但實參中不能有其對應的對象的引用,否則會報錯
3. this引用所解決的問題
看下面給出的代碼, 當方法形參名與成員變量名相同 ;但我們沒有手動通過this引用去調用成員變量;
看執行結果可以發現此時並沒有完成對於成員變量的賦值,因為在方法中遵循局部變量優先的原則,就不會去訪問成員變量,只是形參自己給自己賦值而已
public class Date {
public int year;
public int month;
public int day;
public void setDay(int year, int month, int day){
year = year;
month = month;
day = day;
}
public void printDate(){
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
// 構造三個日期類型的對象 d1 d2 d3
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
// 對d1,d2,d3的日期設置
d1.setDay(2022,8,15);
d2.setDay(2022,8,16);
d3.setDay(2022,8,17);
// 打印日期中的內容
d1.printDate();
d2.printDate();
d3.printDate();
}
}
執行結果:
要解決這裏的問題只需要通過this去訪問成員變量即可,此時就可以區分形參和成員變量了
public void setDay(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
執行結果:
4. this的三種用法
- this.成員變量
- this.成員方法
- this( );訪問構造方法(在構造方法博客中介紹)
二. super關鍵字
1. super關鍵字的介紹
由於設計不好,或者因場景需要,子類和父類中可能會存在相同名稱的成員,如果要在子類方法中訪問父類同名成 員時,該如何操作?
直接訪問是無法做到的,因為局部優先的的原則,會直接訪問子類的成員。
Java提供了 super關鍵字,該關鍵字主要作用:在子類方法中訪問父類的成員。
【注意事項】
- super只能在非靜態方法中使用
-
super可以用來在子類方法中,訪問父類的成員變量和方法。
public class Base { int a; int b; public void methodA(){ System.out.println("Base中的methodA()"); } public void methodB(){ System.out.println("Base中的methodB()"); } } class Derived extends Base{ int a; // 與父類中成員變量同名且類型相同 char b; // 與父類中成員變量同名但類型不同 // 與父類中methodA()構成重載 public void methodA(int a) { System.out.println("Derived中的method()方法"); } // 與基類中methodB()構成重寫 public void methodB(){ System.out.println("Derived中的methodB()方法"); } public void methodC(){ // 對於同名的成員變量,直接訪問時,訪問的都是子類的 a = 100; // 等價於: this.a = 100; b = 101; // 等價於: this.b = 101; // 注意:this是當前對象的引用 // 訪問父類的成員變量時,需要藉助super關鍵字 // super是獲取到子類對象中從基類繼承下來的部分 super.a = 200; super.b = 201; // 父類和子類中構成重載的方法,直接可以通過參數列表區分清訪問父類還是子類方法 methodA(); // 沒有傳參,訪問父類中的methodA() methodA(20); // 傳遞int參數,訪問子類中的methodA(int) // 如果在子類中要訪問重寫的基類方法,則需要藉助super關鍵字 methodB(); // 直接訪問,則永遠訪問到的都是子類中的methodA(),基類的無法訪問到 super.methodB(); //訪問基類的methodB() } }2. super的三種用法
- super.子類中從父類繼承的成員變量
- super.子類中從父類繼承的成員方法
- super( );調用父類的構造方法(在構造方法博客中介紹)
三. super和this的比較
1. 相同點
- 都是Java中的關鍵字
- 只能在類的非靜態方法中使用,用來訪問非靜態成員方法和字段
- 在構造方法中調用時,必須是構造方法中的第一條語句,並且不能同時存在
2. 不同點
- this是當前對象的引用,當前對象即調用實例方法的對象,super相當於是子類對象中從父類繼承下來部分成員的引用(注意不是父類的引用,子類繼承父類並沒有創建父類對象)
- 在非靜態成員方法中,this用來訪問本類的方法和屬性,子類對象中如果沒有重名現象的發生,this也可以訪問到父類繼承下來的方法和屬性;但super只能用來用來訪問父類繼承下來的方法和屬性
- 在構造方法中:this(…)用於調用本類構造方法,super(…)用於調用父類構造方法,兩種調用不能同時在構造方法中出現
- 子類構造方法中一定會存在super(…)的調用 ,用户沒有寫編譯器也會自動給出;但是要在子類構造方法中調用子類其他構造方法,需要用户手動添加this(…)
四. 代碼塊概念以及分類
使用 { } 定義的一段代碼稱為代碼塊。
根據代碼塊定義的位置以及關鍵字,又可分為以下四種:
- 普通代碼塊
- 構造代碼塊
- 靜態代碼塊
- 同步代碼塊
1. 普通代碼塊
普通代碼塊:定義在方法中的代碼塊, 其內的變量只在代碼塊中有效,這種用法較少見。
public class Main{
public static void main(String[] args) {
{
//直接使用{ }定義,普通方法塊
int x = 10 ;
System.out.println("x1 = " +x);
}
int x = 100 ;
System.out.println("x2 = " +x);
}
}
2. 構造代碼塊
定義在類中的代碼塊(不加修飾符)。
也叫: 實例代碼塊 。構造代碼塊一般用於初始化實例成員變量。
public class Student{
//實例成員變量
private String name;
private String gender;
private int age;
//實例代碼塊
{
this.name = "xinxin";
this.age = 21;
this.gander = "nan";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" gender: "+gender);
}
}
public class Main {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
3. 靜態代碼塊
使用static定義的代碼塊稱為靜態代碼塊。一般用於初始化靜態成員變量。
public class Student{
private String name;
private int age;
private static String classRoom;
//實例代碼塊
{
this.name = "xin";
this.age = 21;
System.out.println("I am instance init()!");
}
// 靜態代碼塊
static {
classRoom = "rj2104";
System.out.println("I am static init()!");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
}
}
4. 注意事項
- 靜態代碼塊不管生成多少個對象,其只會執行一次
- 靜態成員變量是類的屬性,因此是在JVM加載類時開闢空間並初始化的
- 如果一個類中包含多個靜態代碼塊,在編譯代碼時,編譯器會按照定義的先後次序依次執行(合併)
- 實例代碼塊只有在創建對象時才會執行