最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入介紹Java對象初始化

 更新時間:2016年07月25日 10:41:28   作者:蕭蕭弈寒  
本文對Java如何執(zhí)行對象的初始化做一個詳細深入地介紹。有需要的小伙伴們可以參考。

前言

在Java中,一個對象在可以被使用之前必須要被正確地初始化,這一點是Java規(guī)范規(guī)定的。

自動初始化(默認值)

一個類的所有基本數據成員都會得到初始化,運行下面的例子可以查看這些默認值:

class Default{
  boolean t;
  char c;
  byte b;
  short s;
  int i;
  long l;
  float f;
  double d;
  public void show() {
    System.out.println("基本類型  初始化值\n"+
            "boolean<----->" + t +"\n" +
            "char<----->" + c +"\n" +
            "byte<----->" + b + "\n" +
            "short<----->" + s + "\n" +
            "int<----->" + i + "\n" +
            "long<----->" + l + "\n" +
            "float<----->" + f + "\n" +
            "double<----->" + d + "\n"
    );

  }
}
public class InitValue {
  public static void main(String[] args) {
    Default d = new Default();
    d.show();
  }
}

【運行結果】:

基本類型   初始化值

boolean<----->false

char<----->

byte<----->0

short<----->0

int<----->0

long<----->0

float<----->0.0

double<----->0.0

其中,char類型的默認值為空(null)。

對于非基本數據類型而言,對象的句柄也會被初始化:

class Person {
  private String name;
  // setter
}
class Default {
  Person p;
  public void show() {
    System.out.println("Person<----->" + p);
  }
}
public class InitValue {
  public static void main(String[] args) {
    Default d = new Default();
    d.show();
  }
}

【運行結果】:

Person<----->null

可見,句柄初始化值為null。這就是說,如果沒有為p指定初始化值就調用類似于p.setName的方法,就會出現異常。

規(guī)定初始化

如果需要自己為變量賦一個初始值,可以在定義變量的同時賦值。

class Default{
  boolean t = true;
  char c = 'A';
  byte b = 47;
  short s = 0xff;
  int i = 24;
  long l = 999;
  float f = 1.2f;
  double d = 1.732;
  public void show() {
    System.out.println(
            "boolean<----->" + t +"\n" +
            "char<----->" + c +"\n" +
            "byte<----->" + b + "\n" +
            "short<----->" + s + "\n" +
            "int<----->" + i + "\n" +
            "long<----->" + l + "\n" +
            "float<----->" + f + "\n" +
            "double<----->" + d + "\n"
    );

  }
}
public class InitValue {
  public static void main(String[] args) {
    Default d = new Default();
    d.show();
  }
}

甚至可以通過一個方法來進行初始化;

class Person {
  int i = set();
  //...
}

這些方法也可以使用自變量:

class Person {
  int i;
  int j = set(i);
  //...
}

構建器初始化

構建器進行初始化的優(yōu)點是可以在運行期決定初始化值。例如:

class Person {
  int age;
  Person() {
    age = 89;
  }
}

age首先會初始化為0,然后變成89。對于所有基本類型以及對象的句柄,這種情況都是成立的。

初始化順序

在一個類里,初始化的順序是由變量在類內的定義順序決定的。即使變量定義大量遍布于方法定義的中間,那么變量仍然會在調用任何方法(包括構造函數)之前得到初始化。例如:

class Pet {
  Pet(int age) {
    System.out.println("Pet(" + age + ")");
  }
}

class Person {
  Pet t1 = new Pet(1);

  Person() {
    System.out.println("---Person()---");
    t3 = new Pet(33);
  }

  Pet t2 = new Pet(2);
  void show() {
    System.out.println("show----running");
  }
  Pet t3 = new Pet(3);
}


public class OrderOfInitialization {
  public static void main(String[] args) {
    Person p = new Person();
    p.show();
  }
}

【運行結果】:

Pet(1)

Pet(2)

Pet(3)

---Person()---

Pet(33)<br/>

show----running

上例中,雖然t1、t2、t3的定義遍布于類中,但是初始化的先后順序是由t1、t2、t3的定義順序決定的(自己動手調換t1、t2、t3看看結果),且初始化優(yōu)先于構建器執(zhí)行,當調用Person的構建器時,t3重新初始化。

靜態(tài)數據的初始化

如果數據是靜態(tài)的(static),同樣的過程也會執(zhí)行。若屬于基本類型,而且未對其進行初始化,就會自動獲得自己的標準基本類型初始值;若它是指向一個對象的句柄,除非創(chuàng)建一個對象同它連接起來,否則得到一個空值(null)。如果在定義時初始化,采取的方式與非靜態(tài)值是不同的,這是因為static只有一個存儲區(qū)域。例如:

class Bowl {
  Bowl(int marker) {
    System.out.println("Bowl(" + marker + ")");
  }
  void f(int marker) {
    System.out.println("f(" + marker + ")");
  }
}

class Table {
  static Bowl b1 = new Bowl(1);
  Table() {
    System.out.println("Table()");
    b2.f(1);
  }
  void f2(int marker) {
    System.out.println("f2(" + marker + ")");
  }
  static Bowl b2 = new Bowl(2);
}

class Cupboard {
  Bowl b3 = new Bowl(3);
  static Bowl b4 = new Bowl(4);
  Cupboard() {
    System.out.println("Cupboard()");
    b4.f(2);
  }
  void f3 (int marker) {
    System.out.println("f3(" + marker + ")");
  }
  static Bowl b5 = new Bowl(5);
}

public class StaticInitialization {
  public static void main(String[] args) {
    System.out.println("Creating new Cupboard() in main");
    new Cupboard();
    System.out.println("Creating new Cupboard() in main");
    new Cupboard();
    t2.f2(1);
    t3.f3(1);
  }
  static Table t2 = new Table();
  static Cupboard t3 = new Cupboard();
}

【運行結果】:

Bowl(1)

Bowl(2)

Table()

f(1)

Bowl(4)

Bowl(5)

Bowl(3)

Cupboard()

f(2)

Creating new Cupboard() in main

Bowl(3)

Cupboard()

f(2)

Creating new Cupboard() in main

Bowl(3)

Cupboard()

f(2)

f2(1)

f3(1)

靜態(tài)代碼塊

Java允許將其他static初始化工作劃分到類內一個特殊的代碼塊中,這種代碼塊的形式為static關鍵字,后面跟著一個方法主體,稱為靜態(tài)代碼塊。靜態(tài)代碼塊只有在第一次生成那個類的對象或首次訪問屬于那個類的static成員時執(zhí)行。例如:

class Person {
  Person(int age) {
    System.out.println("Person(" + age + ")");
  }
  void f(int age) {
    System.out.println("f(" + age + ")");
  }
}

class Persons {
  static Person p1;
  static Person p2;
  static {
    p1 = new Person(1);
    p2 = new Person(2);
  }
  Persons() {
    System.out.println("Persons()");
  }
}

public class ExplicitStatic {
  public static void main(String[] args) {
    System.out.println("Inside main()");
    Persons.p1.f(18);//1
  }
  static Persons x = new Persons();//2
  static Persons y = new Persons();//2
}

在標記為1的行內訪問static對象p1的時候,或在行1被注釋而行2未被注釋是,用于Persons的static初始化模塊就會運行。若1和2都被注釋掉,則用于Persons的靜態(tài)代碼塊不會執(zhí)行。

靜態(tài)屬性和靜態(tài)代碼塊執(zhí)行的先后順序

class Person {
  Person(int age) {
    System.out.println("Person("+age+")");
  }
}
class Persons {
  static Person p = new Person(2); // 1
  static {
    p = new Person(3);
  }
  static Person p = new Person(2); // 2

}
public class CompStaticInit {
  public static void main(String[] args) {

  }
  static Persons x = new Persons();
}

根據注釋1保留2,注釋2保留1的結果分析可知,靜態(tài)屬性和靜態(tài)代碼塊的執(zhí)行順序取決于編碼的順序。誰在前面就先執(zhí)行誰。

非靜態(tài)屬性的初始化

class Animal {
  Animal(int age) {
    System.out.println("Animal(" + age + ")");
  }
  void f(int age) {
    System.out.println("f(" + age + ")");
  }
}
public class NotStaticInit {
  Animal a1;
  Animal a2;
  {
    a1 = new Animal(1);
    a2 = new Animal(2);
    System.out.println("a1 & a2 initialized");
  }
  NotStaticInit() {
    System.out.println("NotStaticInit");
  }
  public static void main(String[] args) {
    System.out.println("Inside main()");
    NotStaticInit x = new NotStaticInit();
  }
}

類似于靜態(tài)代碼塊,匿名代碼塊與非靜態(tài)屬性的初始化順序取決于編碼順序。

繼承中的對象初始化過程

class Insect {
  int i = 1;
  int j;

  Insect() {
    prt("i = " + i + ", j = " + j);
    j = 2;
  }

  static int x1 = prt("static Insect.x1 initialized");

  static int prt(String s) {
    System.out.println(s);
    return 3;
  }
}

public class Beetle extends Insect {
  int k = prt("Beeklt.k initialized");

  Beetle() {
    prt("k = " + k);
    prt("j = " + j);
  }

  static int x2 = prt("static Bootle.x2 initialized");
  static int prt(String s) {
    System.out.println(s);
    return 4;
  }

  public static void main(String[] args) {
    prt("Beetle constructor");
    Beetle b = new Beetle();
  }
}

【運行結果】:

static Insect.x1 initialized

static Bootle.x2 initialized

Beetle constructor

i = 1, j = 0

Beeklt.k initialized

k = 4

j = 2

對Beetle運行Java時,發(fā)生的第一件事情是裝載程序到外面找到那個類。在裝載過程中,裝載程序發(fā)現一個基礎類,所以隨之將其載入。無論是否生成基礎類的對象,這一過程都將執(zhí)行。如果基礎類含有另一個基礎類,則另一個基礎類隨即也會載入,以此類推。接下來就在根基礎類中執(zhí)行static初始化,再在下一個衍生類中執(zhí)行,以此類推。這是因為衍生類的初始化可能要依賴于對基礎類成員的初始化。

當類都裝載完畢,就能創(chuàng)建對象。首先,這個對象中的所有基本數據類型都會設置成為他們的默認值,對象句柄設為null。然后執(zhí)行基礎類的構建器。這種情況是自動完成的(衍生類的構造函數中默認調用了super(),也可以通過super指定基類的構建器)?;A類構建器完成后,衍生類實例變量就會按本來的順序得到初始化,然后執(zhí)行構建器的剩余的主體部分。

總結對象創(chuàng)建的過程:

    靜態(tài)只在類加載的時候執(zhí)行且只執(zhí)行一次;

    非靜態(tài)只有在實例化的時候執(zhí)行,每次創(chuàng)建對象都執(zhí)行;

    靜態(tài)在非靜態(tài)之前執(zhí)行,基類靜態(tài)優(yōu)先于衍生類靜態(tài)執(zhí)行;

    靜態(tài)屬性和靜態(tài)代碼塊的執(zhí)行屬性取決于它們在類中的位置,誰在前先執(zhí)行誰;

    非靜態(tài)屬性和構造塊的執(zhí)行順序取決于它們在類中的位置,誰在前執(zhí)行誰。

總結

通過上面的介紹,我們對Java中初始化對象的幾種方式以及通過何種方式執(zhí)行初始化代碼有了了解,同時也對何種情況下我們可能會使用到未經初始化的變量進行了介紹。在對這些問題有了詳細的了解之后,就可以在編碼中規(guī)避一些風險,保證一個對象在可見之前是完全被初始化的。

相關文章

  • Spring核心方法refresh的使用解析

    Spring核心方法refresh的使用解析

    這篇文章主要介紹了Spring核心方法refresh的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 使用Filter實現登錄權限驗證

    使用Filter實現登錄權限驗證

    這篇文章主要為大家詳細介紹了使用Filter實現登錄權限驗證,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Spring Boot JDBC 連接數據庫示例

    Spring Boot JDBC 連接數據庫示例

    本篇文章主要介紹了Spring Boot JDBC 連接數據庫示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • SpringBoot JSON全局日期格式轉換器實現方式

    SpringBoot JSON全局日期格式轉換器實現方式

    這篇文章主要介紹了SpringBoot JSON全局日期格式轉換器,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 解析Java?中for循環(huán)和foreach循環(huán)哪個更快

    解析Java?中for循環(huán)和foreach循環(huán)哪個更快

    這篇文章主要介紹了Java中for循環(huán)和foreach循環(huán)哪個更快示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • 使用IDEA配置Tomcat和連接MySQL數據庫(JDBC)詳細步驟

    使用IDEA配置Tomcat和連接MySQL數據庫(JDBC)詳細步驟

    這篇文章主要介紹了使用IDEA配置Tomcat和連接MySQL數據庫(JDBC)詳細步驟,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • SpringBoot對PDF進行模板內容填充與電子簽名合并詳解

    SpringBoot對PDF進行模板內容填充與電子簽名合并詳解

    這篇文章主要為大家詳細介紹了SpringBoot對PDF進行模板內容填充與電子簽名合并的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以參考下
    2023-12-12
  • Java實現的校驗銀行卡功能示例

    Java實現的校驗銀行卡功能示例

    這篇文章主要介紹了Java實現的校驗銀行卡功能,結合完整實例形式分析了java針對銀行卡類型、歸屬地等信息的判斷、讀取相關操作技巧,需要的朋友可以參考下
    2018-06-06
  • 教你用java完美封裝微信模板消息的發(fā)送動態(tài)

    教你用java完美封裝微信模板消息的發(fā)送動態(tài)

    這篇文章主要介紹了教你用java完美封裝微信模板消息的發(fā)送動態(tài),文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • ZooKeeper開發(fā)實際應用案例實戰(zhàn)

    ZooKeeper開發(fā)實際應用案例實戰(zhàn)

    這篇文章主要為大家介紹了ZooKeeper開發(fā)的實際應用案例實戰(zhàn),文中附含詳細開發(fā)應用源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-01-01

最新評論

仁布县| 河间市| 大化| 咸宁市| 和田县| 厦门市| 四子王旗| 兰溪市| 聂拉木县| 武鸣县| 凤庆县| 宁强县| 宜兴市| 米林县| 楚雄市| 固始县| 吴旗县| 莱芜市| 渭源县| 米易县| 三门县| 邳州市| 三台县| 长宁县| 松滋市| 嘉定区| 墨玉县| 三门县| 宣汉县| 满洲里市| 哈密市| 永平县| 静乐县| 赫章县| 阜城县| 新丰县| 阿巴嘎旗| 象山县| 越西县| 眉山市| 新泰市|