91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中的類與繼承

發布時間:2020-07-03 12:37:15 來源:網絡 閱讀:123 作者:buyinuan 欄目:編程語言

對于面向對象的程序設計語言來說,類毫無疑問是其最重要的基礎。抽象、封裝、繼承、多態這四大特性都離不開類,只有存在類,才能體現面向對象編程的特點,今天我們就來了解一些類與繼承的相關知識。

一、Java類簡介

在Java中,類文件是以.java為后綴的代碼文件,在每個類文件中最多只允許出現一個public類,當有public類的時候,類文件的名稱必須和public類的名稱相同,若不存在public,則類文件的名稱可以為任意的名稱(當然以數字開頭的名稱是不允許的)。

  對于類的成員變量,如果在定義的時候沒有進行顯示的賦值初始化,則Java會保證類的每個成員變量都得到恰當的初始化:

  1)對于  char、short、byte、int、long、float、double等基本數據類型的變量來說會默認初始化為0(boolean變量默認會被初始化為false);我們在定義類時,類的成員變量可以不用賦初始值,因為在類加載時JVM已經給類變量賦了默認的初始值,但是類的局部變量(方法中定義的變量)必須先賦初始值后才能使用,否則會報錯。

  2)對于引用類型的變量,會默認初始化為null。

  如果沒有顯示地定義構造器,則編譯器會自動創建一個無參構造器,但是要記住一點,如果顯示地定義了構造器,編譯器就不會自動添加構造器。

  下面我們著重講解一下初始化順序:

  當程序執行時,需要生成某個類的對象,Java執行引擎會先檢查是否加載了這個類,如果沒有加載,則先執行類的加載再生成對象,如果已經加載,則直接生成對象。

在類的加載過程中,類的static成員變量會被先加載,另外如果類中有static語句塊,則會執行static語句塊。static成員變量和static語句塊的執行順序同代碼中的順序一致。記住,在Java中,類是按需加載,只有當需要用到這個類的時候,才會加載這個類,并且只會加載一次。

在生成對象的過程中,會先初始化對象的成員變量,然后再執行構造器。也就是說類中的變量會在任何方法(包括構造器)調用之前得到初始化。以下通過示例說明類的初始化順序:

/**
 * Java初始化執行順序
 */
public class InitSeq {

    private static int var;

    static {
        System.out.println("static block");
    }

    public InitSeq() {
        System.out.println("init class");
    }
    
    private Inner inner = new Inner();

    public static void main(String[] args) {
        InitSeq initSeq = new InitSeq();
        Inner inner1 = new Inner();
        System.out.println(var);
    }
}

class Inner {

        static {
            System.out.println("inner static block");
        }

    public Inner() {
        System.out.println("inner class init");
    }
}

以上程序的執行結果為:

static block
inner static block
inner class init
init class
inner class init
0

結果說明:在加載InitSeq類的時候,首先執行static塊中的內容,然后初始化類成員變量inner,Inner類中的static塊在類加載后執行且static塊只有在類加載時執行,所以雖然Inner類實例化了兩次(inner、inner1),但static塊只會執行一次,最后執行構造器函數完成類的初始化,類成員變量var沒有顯示的賦值,默認初始值為0。


二、Java繼承

繼承是所有面向對象語言不可缺少的部分,在java中使用extends關鍵字來表示繼承關系。Objece類是所有類的父類,當創建一個類時如果沒有明確指出要繼承的類,就總是隱式地從根類Object進行繼承,子類可以直接訪問父類中非私有的屬性和方法,繼承提高了代碼的復用性,繼承讓類與類直接產生了關系,提供了多態的前提;

需要特別說明的是:Java只支持單繼承也就是說 一個類最多只能顯示地繼承于一個父類。但是一個類卻可以被多個類繼承,也就是說一個類可以擁有多個子類。

1、子類繼承父類的成員變量

當子類繼承了某個類之后,便可以使用父類中的成員變量,但是并不是完全繼承父類的所有成員變量。具體的原則如下:

a、子類能夠繼承父類中public和protected修飾的成員變量,不能繼承父類中private修飾的成員變量,也無法訪問父類中private修飾的成員變量(只能通過getter方法訪問)

b、對于父類中包訪問權限的成員變量,如果父類和子類在同一個包下,那么子類可以繼承,否則子類不能繼承。

c、對于父類中可以繼承的成員變量,如果子類中出現了同名的成員變量,則會發生隱藏現象,即子類的變量會屏蔽父類的成員變量,如果想要訪問父類同名的成員變量則需要使用關鍵字super

/**
 * 父類
 */
public class FatherClazz {

    /**
     * 姓名
     */
    public String name;

    /**
     * 性別
     */
    protected String sex;

    /**
     * 年齡
     */
    private int age;
}

/**
 * 子類
 */
public class SonClazz extends FatherClazz{

    /**
     * 父類中存在相同的變量
     * 子類中會屏蔽父類的變量
     */
    public String name;

    /**
     * 使用super關鍵字訪問父類同名變量
     */
    public SonClazz() {
        this.name = "son";
        super.name = "father";
        this.sex = "男";
    }
}


2、子類繼承父類的方法

方法的繼承和成員變量的繼承類似

a、子類能夠繼承父類中public和protected修飾的方法,不能繼承父類中private修飾的方法,也無法訪問父類中private修飾的方法

b、對于父類中包訪問權限的方法,如果父類和子類在同一個包下,那么子類可以繼承,否則子類不能繼承。

c、對于父類中可以繼承的成員變量,如果子類中出現了相同的方法,則會發生覆蓋現象,即子類的方法會覆蓋父類的方法,如果想要訪問父類相同的方法則需要使用關鍵字super

/**
 * 父類
 */
public class FatherClazz {

    /**
     * 姓名
     */
    public String name;

    /**
     * 性別
     */
    protected String sex;

    /**
     * 年齡
     */
    private int age;

    public void sayHello() {
        System.out.println("hello fatherClazz, My Name is " + name);
    }
}

/**
 * 子類
 */
public class SonClazz extends FatherClazz{

    /**
     * 父類中存在相同的變量
     * 子類中會屏蔽父類的變量
     */
    public String name;

    /**
     * 使用super關鍵字訪問父類同名變量
     */
    public SonClazz() {
        this.name = "son";
        super.name = "father";
        this.sex = "男";
    }

    public static void main(String[] args) {
        SonClazz sonClazz = new SonClazz();
        sonClazz.sayHello();
        sonClazz.extendMethod();
    }

    /**
     * 子類方法覆蓋父類方法
     */
    @Override
    public void sayHello() {
        // 訪問父類方法,使用super關鍵字
        super.sayHello();
        System.out.println("hello sonClazz, My Name is " + name);
    }
}

執行結果為:

hello fatherClazz, My Name is father
hello sonClazz, My Name is son
this extend method

3、子類初始化說明

子類在初始化時,會先初始化父類,但是子類是不能夠繼承父類的構造器,如果父類的構造器都是帶有參數的,則必須在子類的構造器中顯示地通過super關鍵字調用父類的構造器并配以適當的參數列表。否則無法初始化父類。如果父類有無參構造器,則在子類的構造器中用super關鍵字調用父類構造器不是必須的,如果沒有使用super關鍵字,系統會自動調用父類的無參構造器。

/**
 * 父類
 */
public class FatherClazz {

    /**
     * 姓名
     */
    public String name;

    /**
     * 性別
     */
    protected String sex;

    /**
     * 年齡
     */
    private int age;

    /**
     * 帶參數的構造函數
     */
    public FatherClazz(String name) {
        this.name = name;
        System.out.println("fatherClazz init");
    }

    public void sayHello() {
        System.out.println("hello fatherClazz, My Name is " + name);
    }

    public void extendMethod() {
        System.out.println("this extend method");
    }
}

/**
 * 子類
 */
public class SonClazz extends FatherClazz{

    /**
     * 父類中存在相同的變量
     * 子類中會屏蔽父類的變量
     */
    public String name;

    /**
     * 使用super關鍵字訪問父類同名變量
     */
    public SonClazz() {
        // 由于父類的構造函數帶參數,且父類中沒有無參的構造函數
        // 那么在子類的構造函數中必須使用super()顯示的調用父類的構造函數,完成父類的初始化
        // 如果父類中有無參的構造函數,則無需使用super調用構造函數,JVM默認使用無參的構造函數完成初始話
        super("father");
        this.name = "son";
        this.sex = "男";
        System.out.println("sonClazz init");
    }

    public static void main(String[] args) {
        SonClazz sonClazz = new SonClazz();
        sonClazz.sayHello();
        sonClazz.extendMethod();
    }

    /**
     * 子類方法覆蓋父類方法
     */
    @Override
    public void sayHello() {
        // 訪問父類方法,使用super關鍵字
        super.sayHello();
        System.out.println("hello sonClazz, My Name is " + name);
    }
}

執行結果為:

fatherClazz init
sonClazz init
hello fatherClazz, My Name is father
hello sonClazz, My Name is son
this extend method

結果分析:在初始化子類時,會先初始化父類,由于父類沒有無參的構造函數,所有在子類的構造函數中使用super(),顯示的調用了父類的構造函數完成了父類的初始化。需要特別強調的是:父類的構造器調用以及初始化過程一定在子類的前面

static變量、static塊加載順序額外說明,示例如下:

示例一:

/**
 * static加載說明
 */
public class TestClazz extends Base{

    static{
        System.out.println("test static");
    }

    public TestClazz(){
        System.out.println("testClazz constructor");
    }

    public static void main(String[] args) {
        new TestClazz();
    }
}
class Base{

    private Test test = new Test();

    static{
        System.out.println("base static");
    }

    public Base(){
        System.out.println("base constructor");
    }
}

class Test {

    public Test() {
        System.out.println("test constructor");
    }
}

執行結果為:

base static
test static
test constructor
base constructor
testClazz constructor

結果說明:執行TestClazz的main方法時,首先需要加載TestClazz類,由于TestClazz類繼承了Base所以要先加載Base類,加載類時會加載static變量和static塊,所以先執行了Base類中的static塊,Base類加載完成后,加載TestClazz類,執行TestClazz中的static塊,類加載完成后,執行new TestClazz(),進行類的實例化,由于繼承了Base類,同樣需要先實例化Base類,Base中定義了成員變量test,需要先示例化成員變量,然后執行構造函數,完成Base類的實例化,最后執行TestClazz類的構造函數,完成TestClazz類的實例化。

示例二:

/**
 * static加載說明
 */
public class TestClazz extends Base{

    static{
        System.out.println("test static");
    }

    public TestClazz(){
        System.out.println("testClazz constructor");
    }

    public static void main(String[] args) {
        new TestClazz();
    }
}
class Base{

    // test變量為static類型,在類加載的時候,就會完成類的示例化
    private static Test test = new Test();

    static{
        System.out.println("base static");
    }

    public Base(){
        System.out.println("base constructor");
    }
}

class Test {

    public Test() {
        System.out.println("test constructor");
    }
}

執行結果:

test constructor
base static
test static
base constructor
testClazz constructor

結果說明:示例一和示例二唯一的區別就是,Base類中的test變量類型變為static類型,結果就是在加載Base類時就將test變量實例化了。



由于篇幅有限文章中的代碼無法一一列出,如需獲取全部的源碼信息,可關注微信公眾號 布衣暖,回復 java基礎 獲取全部的源碼信息

Java中的類與繼承









向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盐山县| 安吉县| 南靖县| 鹤山市| 开远市| 吉首市| 黑河市| 营山县| 湖北省| 沙河市| 随州市| 广河县| 东辽县| 禹城市| 理塘县| 堆龙德庆县| 赣州市| 封开县| 吐鲁番市| 五河县| 中方县| 志丹县| 南投市| 海林市| 南昌县| 龙泉市| 红桥区| 留坝县| 吉水县| 本溪市| 临潭县| 沁阳市| 大埔区| 保康县| 西宁市| 铜山县| 台江县| 霸州市| 永春县| 白河县| 顺平县|