1. 程式人生 > >Java 面向物件程式設計之四個關鍵字

Java 面向物件程式設計之四個關鍵字

this,super,static,final是四個常見的類的關鍵字,怎麼樣來描述類的屬性和行為?
如果一個類從另外一個類繼承,我們new這個子類的例項物件的時候,這個子類物件裡面會有一個父類物件。怎麼去引用裡面的父類物件呢?使用super來引用,this指的是當前物件的引用,super是當前物件裡面的父物件的引用。static和final可以用來修飾變數,方法,類,他們有各自的特點。

1. this

this代表物件的引用(誰呼叫就代表誰), 必須放在非靜態方法裡面,this是自身的一個物件,代表物件本身, 指向物件本身的一個指標。
參考 Java關鍵字this
主要作用:


在這裡插入圖片描述

(1)this呼叫本類中的屬性,也就是類中的成員變數;

   Public Class Student { 
     String name; //定義一個成員變數name
     private void SetName(String name) { //定義一個引數(區域性變數)name
      this.name=name; //將區域性變數的值傳遞給成員變數
     }
   } //   this這個關鍵字其代表的就是物件中的成員變數或者方法。
 

(2)this呼叫本類中的其他方法;

public class Student { //定義一個類,類的名字為student。 
 public Student() { //定義一個方法,名字與類相同故為構造方法
  this(“Hello!”);
    }
 public Student(String name) { //定義一個帶形式引數的構造方法
    }
}

(3)this呼叫本類中的其他構造方法,呼叫時要放在構造方法的首行。

ublic Class Student {
 String name; //定義一個成員變數name
 private void SetName(String name) { //定義一個引數(區域性變數)name
this.name=name; //將區域性變數的值傳遞給成員變數
}
Return this
}

2. super

super主要作用:

   1:主要存在於子類方法中,用於指向子類物件中父類物件。
   2:訪問父類的屬性
   3:訪問父類的函式
   4:訪問父類的建構函式

super主要有兩種用法:
  1)super.成員變數/super.成員方法;
  2)super(parameter1,parameter2…)
第一種用法主要用來在子類中呼叫父類的同名成員變數或者方法;第二種主要用在子類的構造器中顯示地呼叫父類的構造器,要注意的是,如果是用在子類構造器中,則必須是子類構造器的第一個語句。
super是一個關鍵字,代表父類的儲存空間標識。(可以理解為父親的引用)
程式例項:

//父類
class FatherClass {
    public int value;
    public void f() {
        value=100;
        System.out.println("父類的value屬性值="+value);
    }
}
 // 子類ChildClass從父類FatherClass繼承  
class ChildClass extends FatherClass {
    /**
     * 子類除了繼承父類所具有的valu屬性外,自己又另外聲明瞭一個value屬性,
     * 也就是說,此時的子類擁有兩個value屬性。
     */
    public int value;
      //在子類ChildClass裡面重寫了從父類繼承下來的f()方法裡面的實現,即重寫了f()方法的方法體。     
    public void f() {
        super.f();//使用super作為父類物件的引用物件來呼叫父類物件裡面的f()方法
        value=200;//這個value是子類自己定義的那個valu,不是從父類繼承下來的那個value
        System.out.println("子類的value屬性值="+value);
        System.out.println(value);//打印出來的是子類自定義的那個value的值,這個值是200
        /**
         * 打印出來的是父類裡面的value值,由於子類在重寫從父類繼承下來的f()方法時,
         * 第一句話“super.f();”是讓父類物件的引用物件呼叫父類物件的f()方法,
         * 即相當於是這個父類物件自己呼叫f()方法去改變自己的value屬性的值,由0變了100。
         * 所以這裡打印出來的value值是100。
         */
        System.out.println(super.value);
    }
}
/**測試類*/
public class tEST1 {
    public static void main(String[] args) {
        ChildClass cc = new ChildClass();
        cc.f();
    }
}

執行結果:
在這裡插入圖片描述

3. static

static關鍵字的中文意思是靜態的, 可以修飾字段、方法、內部類。使用該關鍵字修飾的內容,在面向物件中static修飾的內容是隸屬於類,而不是直接隸屬於物件的,故而生命週期與類相同,即在整個程式執行週期有效。所以static修飾的成員變數一般稱作類成員變數,而static修飾的方法一般稱作靜態方法,普通變數和方法屬於物件。
主要有四種用法:
(1)用來修飾成員變數,將其變為類的成員,從而實現所有物件對於該成員的共享;
(2)用來修飾成員方法,將其變為類方法,可以直接使用“類名.方法名”的方式呼叫,常用於工具類;
(3)靜態塊用法,將多個類成員放在一起初始化,使得程式更加規整,其中理解物件的初始化過程非常關鍵;
(4)靜態導包用法,將類的方法直接匯入到當前類中,從而直接使用“方法名”即可呼叫類方法,更加方便。

public class Person {
    String name;
    static  int age;
    public String toString() {
        return "Name:" + name + ", Age:" + age;
    }
       public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;
        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;
        System.out.println(p1);
        System.out.println(p2);
    }
    /**Output
     * Name:zhangsan, Age:10
     * Name:lisi, Age:12
     *///
}

記憶體分析:::
在這裡插入圖片描述

4. final

final是一個關鍵字,用於修飾類,成員變數,成員方法。
特點:它修飾的類不能被繼承。它修飾的成員變數是一個常量。它修飾的成員方法是不能被子類重寫的。
final修飾的常量定義一般都有書寫規範,被final修飾的常量名稱,所有字母都大寫。
final修飾成員變數,必須初始化,初始化有兩種,顯示初始化;構造方法初始化,不能兩個一起初始化

-final關鍵字 主要用法有以下四種:

(1)用來修飾資料,包括成員變數和區域性變數,該變數只能被賦值一次且它的值無法被改變。對於成員變數來講,我們必須在宣告時或者構造方法中對它賦值;
(2)用來修飾方法引數,表示在變數的生存期中它的值不能被改變;
(3)修飾方法,表示該方法無法被重寫;
(4)修飾類,表示該類無法被繼承。
重寫(覆蓋):在子類中定義某方法與其父類有相同的名稱,返回型別和引數(有繼承關係)
過載:JAVA中一個類可以有多個同名方法,引數型別或個數等可以不同。(沒有繼承關係)

  • final和private的區別:
    1.final修飾的類可以訪問;
    private不可以修飾外部類,但可以修飾內部類(其實把外部類私有化是沒有意義的)。
    2.final修飾的方法不可以被子類重寫;
    private修飾的方法表面上看是可以被子類重寫的,其實不可以,子類是看不到父類的私有方法的。
    3.final修飾的變數只能在顯示初始化或者建構函式初始化的時候賦值一次,以後不允許更改;
    private修飾的變數,也不允許直接被子類或一個包中的其它類訪問或修改,但是他可以通過set和get 方法對其改值和取值。

- [ ]super和this的異同:

This指向本類,super指向父類
(1) super(引數):呼叫基類中的某一個建構函式(應該為建構函式中的第一條語句)
this(引數):呼叫本類中另一種形成的建構函式(應該為建構函式中的第一條語句)
(2)super: 它引用當前物件的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員資料或 函式,基類與派生類中有相同成員定義時如:super.變數名 super.成員函資料名(實參)
this:它代表當前物件名(在程式中易產生二義性之處,應使用this來指明當前物件;如果函式的形參與類中的成員資料同名,這時需用this來指明成員變數名)
(3)呼叫super()必須寫在子類構造方法的第一行,否則編譯不通過。每個子類構造方法的第一條語句,都是隱含地呼叫super(),如果父類沒有這種形式的建構函式,那麼在編譯的時候就會報錯。
super()和this()類似,區別是,super()從子類中呼叫父類的構造方法,this()在同一類內呼叫其它方法。super()和this()均需放在構造方法內第一行。儘管可以用this呼叫一個構造器,但卻不能呼叫兩個。
this和super不能同時出現在一個建構函式裡面,因為this必然會呼叫其它的建構函式,其它的建構函式必然也會有super語句的存在,所以在同一個建構函式裡面有相同的語句,就失去了語句的意義,編譯器也不會通過。
this()和super()都指的是物件,所以,均不可以在static環境中使用。包括:static變數,static方法,static語句塊。
從本質上講,this是一個指向本物件的指標, 然而super是一個Java關鍵字。

class Person { 
    public static void prt(String s) { 
       System.out.println(s); 
    } 
       Person() { 
       prt("父類·無引數構造方法: "+"A Person."); 
    }//構造方法(1) 
        Person(String name) { 
       prt("父類·含一個引數的構造方法: "+"A person's name is " + name); 
    }//構造方法(2) 
} 
    public class tEST1 extends Person { 
    tEST1() { 
       super(); // 呼叫父類構造方法(1) 
       prt("子類·呼叫父類”無引數構造方法“: "+"A chinese coder."); 
    }     
    tEST1(String name) { 
       super(name);// 呼叫父類具有相同形參的構造方法(2) 
       prt("子類·呼叫父類”含一個引數的構造方法“: "+"his name is " + name); 
    }     
    tEST1(String name, int age) { 
       this(name);// 呼叫具有相同形參的構造方法(3) 
       prt("子類:呼叫子類具有相同形參的構造方法:his age is " + age); 
    }  
    public static void main(String[] args) { 
       tEST1 cn = new tEST1(); 
       cn = new tEST1("codersai"); 
       System.out.println();
       cn = new tEST1("codersai", 18); 
    } 
}

執行結果如下:
在這裡插入圖片描述

示例程式碼二:

public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static");
    }
     public Test() {
        System.out.println("test constructor");
    }
         public static void main(String[] args) {
        new MyClass();
    }
} 
class Person{
    static{
        System.out.println("person static");
    }
    public Person(String str) {
        System.out.println("person "+str);
    }
}
class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("myclass static");
    }     
    public MyClass() {
        System.out.println("myclass constructor");
    }
}

執行結果如下:

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

過程分析:首先載入Test類,因此會執行Test類中的static塊。接著執行new MyClass(),而MyClass類還沒有被載入,因此需要載入MyClass類。在載入MyClass類的時候,發現MyClass類繼承自Test類,但是由於Test類已經被載入了,所以只需要載入MyClass類,那麼就會執行MyClass類的中的static塊。在載入完之後,就通過構造器來生成物件。而在生成物件的時候,必須先初始化父類的成員變數,因此會執行Test中的Person person = new Person(),而Person類還沒有被載入過,因此會先載入Person類並執行Person類中的static塊,接著執行父類的構造器,完成了父類的初始化,然後就來初始化自身了,因此會接著執行MyClass中的Person person = new Person(),最後執行MyClass的構造器。

引用:
https://www.cnblogs.com/dolphin0520/p/3799052.html

https://www.cnblogs.com/dotgua/p/6354151.html?utm_source=itdadao&utm_medium=referral