欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java的構(gòu)造方法及類的初始化

 更新時間:2022年08月16日 15:51:00   作者:XIN-XIANG榮  
這篇文章主要為大家詳細介紹了Java的構(gòu)造方法及類的初始化,文中的示例代碼講解詳細,對我們學(xué)習(xí)Java有一定的幫助,感興趣的小伙伴可以了解一下

一. 利用構(gòu)造方法給對象初始化

1. 構(gòu)造方法的概念

構(gòu)造方法(也稱為構(gòu)造器)是一個特殊的成員方法,其名字必須與類名相同,在創(chuàng)建對象時,由編譯器自動調(diào)用,并且在整個對象的生命周期內(nèi)只調(diào)用一次。

構(gòu)造方法的作用就是給對象中的成員進行初始化,并不負責(zé)給對象開辟空間。

public class Date {
    public int year;
    public int month;
    public int day;

    // 構(gòu)造方法:
    // 名字與類名相同,沒有返回值類型,設(shè)置為void也不行
    // 一般情況下使用public修飾
    // 在創(chuàng)建對象時由編譯器自動調(diào)用,并且在對象的生命周期內(nèi)只調(diào)用一次
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("Date(int,int,int)方法被調(diào)用了");
    }

    public void printDate() {
        System.out.println(year + "-" + month + "-" + day);
    }

    public static void main(String[] args) {
        // 此處創(chuàng)建了一個Date類型的對象,并沒有顯式調(diào)用構(gòu)造方法
        Date d = new Date(2021, 6, 9);
        // 輸出Date(int,int,int)方法被調(diào)用了
        d.printDate(); // 2021-6-9
    }
}

2. 構(gòu)造方法的特性

1.名字必須與類名相同

2.沒有返回值類型,設(shè)置為void也不行

3.創(chuàng)建對象時由編譯器自動調(diào)用,并且在對象的生命周期內(nèi)只調(diào)用一次

4.絕大多數(shù)情況下使用public來修飾,特殊場景下會被private修飾

5.構(gòu)造方法可以重載(用戶根據(jù)自己的需求提供不同參數(shù)的構(gòu)造方法); 下面兩個構(gòu)造方法:名字相同,參數(shù)列表不同,因此構(gòu)成了方法重載

public class Date {
    public int year;
    public int month;
    public int day;
    
    // 無參構(gòu)造方法
    public Date(){
        this.year = 1900;
        this.month = 1;
        this.day = 1;
    }
    
    // 帶有三個參數(shù)的構(gòu)造方法
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public void printDate(){
        System.out.println(year + "-" + month + "-" + day);
    }
    public static void main(String[] args) {
        Date d = new Date();
        d.printDate();
    }
}

6.如果用戶沒有顯式定義,編譯器會生成一份默認的構(gòu)造方法,生成的默認構(gòu)造方法一定是無參的; 一旦用戶定義,編譯器則不再生成;下面代碼中,沒有定義任何構(gòu)造方法,編譯器會默認生成一個不帶參數(shù)的構(gòu)造方法。

public class Date {
    public int year;
    public int month;
    public int day;
    public void printDate(){
        System.out.println(year + "-" + month + "-" + day);
    }
    public static void main(String[] args) {
        Date d = new Date();
        d.printDate();
    }
}

7.構(gòu)造方法中,可以通過this調(diào)用其他構(gòu)造方法來簡化代碼

【注意事項】

  • 構(gòu)造方法中,通過this(…)去調(diào)用其他構(gòu)造方法,這條語句必須是構(gòu)造方法中第一條語句
  • 多個構(gòu)造方法不可以互相調(diào)用(不能形成環(huán)), 會形成構(gòu)造器的遞歸調(diào)用,但卻沒有調(diào)用的結(jié)束條件
public class Date {
    public int year;
    public int month;
    public int day;
// 無參構(gòu)造方法--內(nèi)部給各個成員賦值初始值,該部分功能與三個參數(shù)的構(gòu)造方法重復(fù)
// 此處可以在無參構(gòu)造方法中通過this調(diào)用帶有三個參數(shù)的構(gòu)造方法
// 但是this(2022,8,16);必須是構(gòu)造方法中第一條語句
    
    public Date(){
//System.out.println(year); 注釋取消掉,編譯會失敗
        this(2022, 8, 16);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
    }
    
    // 帶有三個參數(shù)的構(gòu)造方法
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

3. 子類構(gòu)造方法

在繼承基礎(chǔ)上,子類對象構(gòu)造時,需要先調(diào)用基類構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法。

在子類構(gòu)造方法中,并沒有寫任何關(guān)于基類構(gòu)造的代碼,但是在構(gòu)造子類對象時,先執(zhí)行基類的構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法,

原因在于:子類對象中成員是有兩部分組成的,基類繼承下來的以及子類新增加的部分 。父類和子類, 肯定是先有父再有子,所以在構(gòu)造子類對象時候 ,子類構(gòu)造方法中先要調(diào)用基類的構(gòu)造方法,將從基類繼承下來的成員構(gòu)造完整 ,然后再完成子類自己的構(gòu)造,將子類自己新增加的成員初始化完整 。

【注意事項】

1.若父類顯式定義無參或者默認的構(gòu)造方法,在子類構(gòu)造方法第一行默認有隱含的super()調(diào)用,即調(diào)用基類構(gòu)造方法

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

public class Derived extends Base{
    public Derived(){
// super(); // 注意子類構(gòu)造方法中默認會調(diào)用基類的無參構(gòu)造方法:super(),
// 用戶沒有寫時,編譯器會自動添加,而且super()必須是子類構(gòu)造方法中第一條語句,
// 并且只能出現(xiàn)一次
        System.out.println("Derived()");
    }
}

public class Test {
    public static void main(String[] args) {
        Derived d = new Derived();
    }
}

2.如果父類構(gòu)造方法是帶有參數(shù)的,此時需要用戶為子類顯式定義構(gòu)造方法,并在子類構(gòu)造方法中選擇合適的父類構(gòu)造方法調(diào)用,否則編譯失敗。

public class Animal {
    public String name;
    public int  age;

   public Animal(String name, int age) {
        this.name = name;
        this.age = age;
       System.out.println("Animal(String , int )");
    }

}

public class Dog extends Animal{
    //傻狗  是狗的屬性
    public boolean silly;

   public Dog(String name,int age,boolean silly) {
        //1. 先幫助父類部分初始化 必須放到第一行
        super(name,age);
        this.silly = silly;
        System.out.println("Dog(String ,int ,boolean )");
   }
    public static void main(String[] args) {
        Animal animal2 = new Dog("金毛",6,false);
    }
}

3.在子類構(gòu)造方法中,super(…)調(diào)用父類構(gòu)造時,必須是子類構(gòu)造方法中第一條語句。

4.super(…)只能在子類構(gòu)造方法中出現(xiàn)一次,由與this(…)調(diào)用時也要在第一條語句,所以super(…)不能和this(…)同時出現(xiàn),也就是是說子類構(gòu)造方法中不能使用this(…)

4. 避免在構(gòu)造方法中調(diào)用重寫的方法

一段有坑的代碼. 我們創(chuàng)建兩個類, B 是父類, D 是子類. D 中重寫 func 方法. 并且在 B 的構(gòu)造方法中調(diào)用 func

class B {
    public B() {
// do nothing
        func();
    }
    public void func() {
        System.out.println("B.func()");
    }
}
class D extends B {
    private int num = 1;
    @Override
    public void func() {
        System.out.println("D.func() " + num);
    }
}
public class Main {
    public static void main(String[] args) {
        D d = new D();
    }
}

執(zhí)行結(jié)果:

  • 構(gòu)造 D 對象的同時, 會調(diào)用 B 的構(gòu)造方法.
  • B 的構(gòu)造方法中調(diào)用了 func 方法, 此時會觸發(fā)動態(tài)綁定, 會調(diào)用到 D 中的 func
  • 此時 D 對象自身還沒有構(gòu)造, num 處在未初始化的狀態(tài), 值為 0;如果具備多態(tài)性,num的值應(yīng)該是1.
  • 所以在構(gòu)造函數(shù)內(nèi),盡量避免使用實例方法,除了final和private方法。

【結(jié)論】:

“用盡量簡單的方式使對象進入可工作狀態(tài)”, 盡量不要在構(gòu)造器中調(diào)用方法(如果這個方法被子類重寫, 就會觸發(fā)動態(tài)綁定, 但是此時子類對象還沒構(gòu)造完成), 可能會出現(xiàn)一些隱藏的但是又極難發(fā)現(xiàn)的問題.

二. 對象的默認初始化

在Java方法內(nèi)部定義一個局部變量時,用戶必須要將其賦值或者初始化,否則會編譯失?。?/p>

但對象中的字段(成員變量),用戶不需要將其初始化就可直接訪問使用,這里其原因在于new對象時,jvm會給出字段的默認初始化。

下面是new對象是時,jvm層面執(zhí)行的概述:

1.檢測對象對應(yīng)的類是否加載了,如果沒有加載則加載

2.為對象分配內(nèi)存空間

3.處理并發(fā)安全問題

比如:多個線程同時申請對象,JVM要保證給對象分配的空間不沖突

4.初始化所分配的空間

即:對象空間被申請好之后,對象中包含的成員已經(jīng)設(shè)置好了初始值

數(shù)據(jù)類型默認值
byte0
short0
int0
long0
float0.0f
double0.0
char/u0000
booleanfalse
reference (引用類型)null

5.設(shè)置對象頭信息(關(guān)于對象內(nèi)存模型后面會介紹)

6.調(diào)用構(gòu)造方法,給對象中各個成員賦值

三. 就地初始化對象

在聲明成員變量時,就直接給出了初始值。

代碼編譯完成后,編譯器會將所有給成員初始化的這些語句添加到各個構(gòu)造方法中

public class Date {
    public int year = 1900;
    public int month = 1;
    public int day = 1;
    
    public Date(){
    }
    
    public Date(int year, int month, int day) {
    }
    
    public static void main(String[] args) {
        Date d1 = new Date(2022,8,16);
        Date d2 = new Date();
    }
}

四. 類的初始化順序

1. 普通類(沒有繼承關(guān)系)

靜態(tài)部分(靜態(tài)變量、常量,靜態(tài)代碼塊)

  • 在類加載階段執(zhí)行,類中存在多個靜態(tài)部分時,會按順序執(zhí)行
  • 靜態(tài)代碼塊只會執(zhí)行一次,且靜態(tài)的變量、常量等只會創(chuàng)建一份

非靜態(tài)部分(實例變量、常量、實例代碼塊)

當(dāng)有對象創(chuàng)建時才會執(zhí)行,按順序執(zhí)行

最后執(zhí)行構(gòu)造方法,當(dāng)有對象創(chuàng)建時才會執(zhí)行

代碼演示:

class Person {
    public String name;
    public int age;
    public Organ organ = new Organ();
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("構(gòu)造方法執(zhí)行");
    }
    {
        System.out.println("實例代碼塊執(zhí)行");
    }
    static {
        System.out.println("靜態(tài)代碼塊執(zhí)行");
    }
}
class Organ {
    //...
    public Organ() {
        System.out.println("實例變量::organ");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Person person1 = new Person("xin",21);
        System.out.println("==============");
        Person person2 = new Person("xinxin",20);
    }
}

執(zhí)行結(jié)果:

2. 派生類( 有繼承關(guān)系)

靜態(tài)部分(靜態(tài)變量、常量,靜態(tài)代碼塊)

  • 父類靜態(tài)代碼塊優(yōu)先于子類靜態(tài)代碼塊執(zhí)行,且是最早執(zhí)行
  • 只有第一次實例化子類對象時,父類和子類的靜態(tài)部分會執(zhí)行; 之后再實例化子類對象時,父類和子類的靜態(tài)部分都不會再執(zhí)行

父類非靜態(tài)部分(實例變量、常量、實例代碼塊)和父類構(gòu)造方法

子類非靜態(tài)部分(實例變量、常量、實例代碼塊)和子類構(gòu)造方法

class Person {
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person:構(gòu)造方法執(zhí)行");
    }
    {
        System.out.println("Person:實例代碼塊執(zhí)行");
    }
    static {
        System.out.println("Person:靜態(tài)代碼塊執(zhí)行");
    }
}
class Student extends Person{
    public Student(String name,int age) {
        super(name,age);
        System.out.println("Student:構(gòu)造方法執(zhí)行");
    }
    {
        System.out.println("Student:實例代碼塊執(zhí)行");
    }
    static {
        System.out.println("Student:靜態(tài)代碼塊執(zhí)行");
    }
}
public class TestDemo4 {
    public static void main(String[] args) {
        Student student1 = new Student("張三",19);
        System.out.println("===========================");
        Student student2 = new Student("gaobo",20);

    }
    public static void main1(String[] args) {
        Person person1 = new Person("bit",10);
        System.out.println("============================");
        Person person2 = new Person("gaobo",20);
    }
}

執(zhí)行結(jié)果:

到此這篇關(guān)于詳解Java的構(gòu)造方法及類的初始化的文章就介紹到這了,更多相關(guān)Java初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Myeclipse鏈接Oracle等數(shù)據(jù)庫時lo exception: The Network Adapter could not establish the connection

    Myeclipse鏈接Oracle等數(shù)據(jù)庫時lo exception: The Network Adapter coul

    今天小編就為大家分享一篇關(guān)于Myeclipse鏈接Oracle等數(shù)據(jù)庫時lo exception: The Network Adapter could not establish the connection,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 關(guān)于Java HashMap自動排序的簡單剖析

    關(guān)于Java HashMap自動排序的簡單剖析

    這篇文章主要給大家介紹了關(guān)于Java HashMap自動排序的簡單剖析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring占位符Placeholder的實現(xiàn)原理解析

    Spring占位符Placeholder的實現(xiàn)原理解析

    這篇文章主要介紹了Spring占位符Placeholder的實現(xiàn)原理,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • java中表示一個文件的File類型詳解

    java中表示一個文件的File類型詳解

    Java提供File類,讓我們對文件進行操作,下面這篇文章主要給大家介紹了關(guān)于java中表示一個文件的File類型的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • Java 多線程之兩步掌握

    Java 多線程之兩步掌握

    Java 多線程編程 Java給多線程編程提供了內(nèi)置的支持。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù)
    2021-10-10
  • JAVA判斷空值方法原理解析

    JAVA判斷空值方法原理解析

    這篇文章主要介紹了JAVA判斷空值方法原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Java中性能優(yōu)化的35種方法匯總

    Java中性能優(yōu)化的35種方法匯總

    很多同學(xué)在日常寫Java的時候很少去關(guān)心性能問題,但是在我們寫代碼的過程中必須考慮到性能對程序的影響。小到我們使用位運算來實現(xiàn)算術(shù)運算,大到我們對 Java 代碼的總體架構(gòu)設(shè)計,性能其實離我們很近。本文介紹了Java中性能優(yōu)化的35種方法,需要的朋友可以參考下。
    2017-01-01
  • Spring Boot構(gòu)建框架詳解

    Spring Boot構(gòu)建框架詳解

    這篇文章主要為大家詳細介紹了Spring Boot構(gòu)建框架的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • SpringBoot自動裝配之@Enable深入講解

    SpringBoot自動裝配之@Enable深入講解

    這篇文章主要介紹了SpringBoot自動裝配之@Enable,SpringBoot中提供了很多Enable開頭的注解,這些注解都是用于動態(tài)啟用某些功能的。而其底層原理是使用@Import注?解導(dǎo)入一些配置類,實現(xiàn)Bean的動態(tài)加載
    2023-01-01
  • Spring零基礎(chǔ)到進階之鴻蒙開篇

    Spring零基礎(chǔ)到進階之鴻蒙開篇

    Spring框架是一個開放源代碼的J2EE應(yīng)用程序框架,由Rod Johnson發(fā)起,是針對bean的生命周期進行管理的輕量級容器(lightweight container)。 Spring解決了開發(fā)者在J2EE開發(fā)中遇到的許多常見的問題,提供了功能強大IOC、AOP及Web MVC等功能
    2022-07-07

最新評論