<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文把 Java 的構(gòu)造方法吃得透透滴

          共 6994字,需瀏覽 14分鐘

           ·

          2020-12-01 19:02

          同學(xué)們好啊,我是沉默王二。又到了《教妹學(xué) Java》的時(shí)間,我很開心,你很期待,有木有?這是《教妹學(xué) Java》專欄的第 18 篇文章,我們來(lái)談?wù)劇癑ava 中的構(gòu)造方法”。

          強(qiáng)烈推薦:JavaBooks 項(xiàng)目又新增了 15 本好書,包括 SpringBoot、MyBatis、Redis 和 SpringSecurity,需要的同學(xué)可以在后臺(tái)回復(fù)「Java」關(guān)鍵字獲取下載地址。

          “二哥,你怎么把《教妹學(xué) Java》改成《零基礎(chǔ)學(xué) Java》了啊,我都不習(xí)慣了,能不能改回去啊,‘零基礎(chǔ)’感覺(jué)過(guò)于平庸了,‘教妹’的噱頭更足啊,況且你是真的在教妹,沒(méi)什么不好意思的。”三妹一臉認(rèn)真地對(duì)我說(shuō)。

          “那好吧,這篇就改回來(lái)吧。只要保證文章的質(zhì)量,確實(shí)也沒(méi)必要過(guò)于糾結(jié)標(biāo)題和封面?!蔽覕倲偸?,對(duì)三妹繼續(xù)說(shuō),“上一節(jié)學(xué)了 Java 中的方法,接著學(xué)構(gòu)造方法的話,難度就小很多了?!?/p>

          “在 Java 中,構(gòu)造方法是一種特殊的方法,當(dāng)一個(gè)類被實(shí)例化的時(shí)候,就會(huì)調(diào)用構(gòu)造方法。只有在構(gòu)造方法被調(diào)用的時(shí)候,對(duì)象才會(huì)被分配內(nèi)存空間。每次使用 new 關(guān)鍵字創(chuàng)建對(duì)象的時(shí)候,構(gòu)造方法至少會(huì)被調(diào)用一次?!?/p>

          “如果你在一個(gè)類中沒(méi)有看見構(gòu)造方法,并不是因?yàn)闃?gòu)造方法不存在,而是被缺省了,編譯器會(huì)給這個(gè)類提供一個(gè)默認(rèn)的構(gòu)造方法。往大的方面說(shuō),就是,Java 有兩種類型的構(gòu)造方法:無(wú)參構(gòu)造方法和有參構(gòu)造方法?!?/p>

          “注意,之所以叫它構(gòu)造方法,是因?yàn)閷?duì)象在創(chuàng)建的時(shí)候,需要通過(guò)構(gòu)造方法初始化值——就是描寫對(duì)象的那些狀態(tài),對(duì)應(yīng)的是類中的字段。”

          01、創(chuàng)建構(gòu)造方法的規(guī)則有哪些

          構(gòu)造方法必須符合以下規(guī)則:

          • 構(gòu)造方法的名字必須和類名一樣;
          • 構(gòu)造方法沒(méi)有返回類型,包括 void;
          • 構(gòu)造方法不能是抽象的、靜態(tài)的、最終的、同步的,也就是說(shuō),構(gòu)造方法不能通過(guò) abstract、static、final、synchronized 關(guān)鍵字修飾。

          簡(jiǎn)單解析一下最后一條規(guī)則。

          • 由于構(gòu)造方法不能被子類繼承,所以用 final 和 abstract 修飾沒(méi)有意義;
          • 構(gòu)造方法用于初始化一個(gè)對(duì)象,所以用 static 修飾沒(méi)有意義;
          • 多個(gè)線程不會(huì)同時(shí)創(chuàng)建內(nèi)存地址相同的同一個(gè)對(duì)象,所以用 synchronized 修飾沒(méi)有必要。

          構(gòu)造方法的語(yǔ)法格式如下:

          class?class_name?{
          ????public?class_name(){}????//?默認(rèn)無(wú)參構(gòu)造方法
          ????public?ciass_name([paramList]){}????//?定義有參數(shù)列表的構(gòu)造方法
          ????…
          ????//?類主體
          }

          值得注意的是,如果用 void 聲明構(gòu)造方法的話,編譯時(shí)不會(huì)報(bào)錯(cuò),但 Java 會(huì)把這個(gè)所謂的“構(gòu)造方法”當(dāng)成普通方法來(lái)處理。

          /**
          ?*?微信搜索「沉默王二」,回復(fù)?Java
          ?*
          ?*?@author?沉默王二
          ?*?@date?2020/11/26
          ?*/

          public?class?Demo?{
          ????void?Demo(){?}
          }

          void Demo(){} 看起來(lái)很符合構(gòu)造方法的寫法(與類名相同),但其實(shí)只是一個(gè)不符合規(guī)范的普通方法,方法名的首字母使用了大寫,方法體為空,它并不是默認(rèn)的無(wú)參構(gòu)造方法,可以通過(guò)反編譯后的字節(jié)碼驗(yàn)證。

          public?class?Demo?{
          ????public?Demo()?{
          ????}

          ????void?Demo()?{
          ????}
          }

          public Demo() {} 才是真正的無(wú)參構(gòu)造方法。

          不過(guò),可以使用訪問(wèn)權(quán)限修飾符(private、protected、public、default)來(lái)修飾構(gòu)造方法,訪問(wèn)權(quán)限修飾符決定了構(gòu)造方法的創(chuàng)建方式。

          02、 什么是默認(rèn)構(gòu)造方法

          如果一個(gè)構(gòu)造方法中沒(méi)有任何參數(shù),那么它就是一個(gè)默認(rèn)構(gòu)造方法,也稱為無(wú)參構(gòu)造方法。

          /**
          ?*?@author?微信搜「沉默王二」,回復(fù)關(guān)鍵字?PDF
          ?*/

          public?class?Bike?{
          ????Bike(){
          ????????System.out.println("一輛自行車被創(chuàng)建");
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????Bike?bike?=?new?Bike();
          ????}
          }

          在上面這個(gè)例子中,我們?yōu)?Bike 類中創(chuàng)建了一個(gè)無(wú)參的構(gòu)造方法,它在我們創(chuàng)建對(duì)象的時(shí)候被調(diào)用。

          程序輸出結(jié)果如下所示:

          一輛自行車被創(chuàng)建

          通常情況下,無(wú)參構(gòu)造方法是可以缺省的,我們開發(fā)者并不需要顯式的聲明無(wú)參構(gòu)造方法,把這項(xiàng)工作交給編譯器更輕松一些。

          “二哥,默認(rèn)構(gòu)造方法的目的是什么?它為什么是一個(gè)空的???”三妹疑惑地看著我,提出了這個(gè)尖銳的問(wèn)題。

          “三妹啊,默認(rèn)構(gòu)造方法的目的主要是為對(duì)象的字段提供默認(rèn)值,看下面這個(gè)例子你就明白了?!蔽倚赜谐芍竦鼗卮鸬馈?/p>

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?Person?{
          ????private?String?name;
          ????private?int?age;

          ????public?static?void?main(String[]?args)?{
          ????????Person?p?=?new?Person();
          ????????System.out.println("姓名?"?+?p.name?+?"?年齡?"?+?p.age);
          ????}
          }

          輸出結(jié)果如下所示:

          姓名?null?年齡?0

          在上面的例子中,默認(rèn)構(gòu)造方法初始化了 name 和 age 的值,name 是 String 類型,所以默認(rèn)值為 null,age 是 int 類型,所以默認(rèn)值為 0。如果沒(méi)有默認(rèn)構(gòu)造方法的話,這項(xiàng)工作就無(wú)法完成了。

          03、什么是有參構(gòu)造方法

          有參數(shù)的構(gòu)造方法被稱為有參構(gòu)造方法,參數(shù)可以有一個(gè)或多個(gè)。有參構(gòu)造方法可以為不同的對(duì)象提供不同的值。當(dāng)然,也可以提供相同的值。

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?ParamConstructorPerson?{
          ????private?String?name;
          ????private?int?age;

          ????public?ParamConstructorPerson(String?name,?int?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}

          ????public?void?out()?{
          ????????System.out.println("姓名?"?+?name?+?"?年齡?"?+?age);
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????ParamConstructorPerson?p1?=?new?ParamConstructorPerson("沉默王二",18);
          ????????p1.out();

          ????????ParamConstructorPerson?p2?=?new?ParamConstructorPerson("沉默王三",16);
          ????????p2.out();
          ????}
          }

          在上面的例子中,構(gòu)造方法有兩個(gè)參數(shù)(name 和 age),這樣的話,我們?cè)趧?chuàng)建對(duì)象的時(shí)候就可以直接為 name 和 age 賦值了。

          new?ParamConstructorPerson("沉默王二",18);
          new?ParamConstructorPerson("沉默王三",16);

          如果沒(méi)有有參構(gòu)造方法的話,就需要通過(guò) setter 方法給字段賦值了。

          04、如何重載構(gòu)造方法

          在 Java 中,構(gòu)造方法和方法類似,只不過(guò)沒(méi)有返回類型。它也可以像方法一樣被重載。構(gòu)造方法的重載也很簡(jiǎn)單,只需要提供不同的參數(shù)列表即可。編譯器會(huì)通過(guò)參數(shù)的數(shù)量來(lái)決定應(yīng)該調(diào)用哪一個(gè)構(gòu)造方法。

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?OverloadingConstrutorPerson?{
          ????private?String?name;
          ????private?int?age;
          ????private?int?sex;

          ????public?OverloadingConstrutorPerson(String?name,?int?age,?int?sex)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????????this.sex?=?sex;
          ????}

          ????public?OverloadingConstrutorPerson(String?name,?int?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}

          ????public?void?out()?{
          ????????System.out.println("姓名?"?+?name?+?"?年齡?"?+?age?+?"?性別?"?+?sex);
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????OverloadingConstrutorPerson?p1?=?new?OverloadingConstrutorPerson("沉默王二",18,?1);
          ????????p1.out();

          ????????OverloadingConstrutorPerson?p2?=?new?OverloadingConstrutorPerson("沉默王三",16);
          ????????p2.out();
          ????}
          }

          創(chuàng)建對(duì)象的時(shí)候,如果傳遞的是三個(gè)參數(shù),那么就會(huì)調(diào)用 OverloadingConstrutorPerson(String name, int age, int sex) 這個(gè)構(gòu)造方法;如果傳遞的是兩個(gè)參數(shù),那么就會(huì)調(diào)用 OverloadingConstrutorPerson(String name, int age) 這個(gè)構(gòu)造方法。

          05、構(gòu)造方法和方法有什么區(qū)別

          構(gòu)造方法和方法之間的區(qū)別還是蠻多的,比如說(shuō)下面這些:

          06、如何復(fù)制對(duì)象

          復(fù)制一個(gè)對(duì)象可以通過(guò)下面三種方式完成:

          • 通過(guò)構(gòu)造方法
          • 通過(guò)對(duì)象的值
          • 通過(guò) Object 類的 clone() 方法

          1)通過(guò)構(gòu)造方法

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?CopyConstrutorPerson?{
          ????private?String?name;
          ????private?int?age;

          ????public?CopyConstrutorPerson(String?name,?int?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}

          ????public?CopyConstrutorPerson(CopyConstrutorPerson?person)?{
          ????????this.name?=?person.name;
          ????????this.age?=?person.age;
          ????}

          ????public?void?out()?{
          ????????System.out.println("姓名?"?+?name?+?"?年齡?"?+?age);
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????CopyConstrutorPerson?p1?=?new?CopyConstrutorPerson("沉默王二",18);
          ????????p1.out();

          ????????CopyConstrutorPerson?p2?=?new?CopyConstrutorPerson(p1);
          ????????p2.out();
          ????}
          }

          在上面的例子中,有一個(gè)參數(shù)為 CopyConstrutorPerson 的構(gòu)造方法,可以把該參數(shù)的字段直接復(fù)制到新的對(duì)象中,這樣的話,就可以在 new 關(guān)鍵字創(chuàng)建新對(duì)象的時(shí)候把之前的 p1 對(duì)象傳遞過(guò)去。

          2)通過(guò)對(duì)象的值

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?CopyValuePerson?{
          ????private?String?name;
          ????private?int?age;

          ????public?CopyValuePerson(String?name,?int?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}

          ????public?CopyValuePerson()?{
          ????}

          ????public?void?out()?{
          ????????System.out.println("姓名?"?+?name?+?"?年齡?"?+?age);
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????CopyValuePerson?p1?=?new?CopyValuePerson("沉默王二",18);
          ????????p1.out();

          ????????CopyValuePerson?p2?=?new?CopyValuePerson();
          ????????p2.name?=?p1.name;
          ????????p2.age?=?p1.age;
          ????????
          ????????p2.out();
          ????}
          }

          這種方式比較粗暴,直接拿 p1 的字段值復(fù)制給 p2 對(duì)象(p2.name = p1.name)。

          3)通過(guò) Object 類的 clone() 方法

          /**
          ?*?@author?沉默王二,一枚有趣的程序員
          ?*/

          public?class?ClonePerson?implements?Cloneable?{
          ????private?String?name;
          ????private?int?age;

          ????public?ClonePerson(String?name,?int?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}

          ????@Override
          ????protected?Object?clone()?throws?CloneNotSupportedException?{
          ????????return?super.clone();
          ????}

          ????public?void?out()?{
          ????????System.out.println("姓名?"?+?name?+?"?年齡?"?+?age);
          ????}

          ????public?static?void?main(String[]?args)?throws?CloneNotSupportedException?{
          ????????ClonePerson?p1?=?new?ClonePerson("沉默王二",18);
          ????????p1.out();

          ????????ClonePerson?p2?=?(ClonePerson)?p1.clone();
          ????????p2.out();
          ????}
          }

          通過(guò) clone() 方法復(fù)制對(duì)象的時(shí)候,ClonePerson 必須先實(shí)現(xiàn) Cloneable 接口的 clone() 方法,然后再調(diào)用 clone() 方法(ClonePerson p2 = (ClonePerson) p1.clone())。

          07、ending

          “二哥,我能問(wèn)一些問(wèn)題嗎?”三妹精神煥發(fā),沒(méi)有絲毫的疲憊。

          “當(dāng)然可以啊,你問(wèn)?!蔽液苄蕾p三妹孜孜不倦的態(tài)度。

          “構(gòu)造方法真的不返回任何值嗎?”

          “構(gòu)造方法雖然沒(méi)有返回值,但返回的是類的對(duì)象。”

          “構(gòu)造方法只能完成字段初始化的工作嗎?”

          “初始化字段只是構(gòu)造方法的一種工作,它還可以做更多,比如啟動(dòng)線程,調(diào)用其他方法等。”

          “好的,二哥,我的問(wèn)題問(wèn)完了,今天的學(xué)習(xí)可以結(jié)束了!”三妹一臉得意的樣子。

          “那你記得復(fù)習(xí)下一節(jié)的內(nèi)容哦?!备惺艿饺靡呀?jīng)學(xué)到了知識(shí),我也很欣慰。

          強(qiáng)調(diào)一下,《教妹學(xué) Java》面向的是零基礎(chǔ)的 Java 學(xué)習(xí)者,我希望能幫助同學(xué)們輕松邁進(jìn)編程世界的大門,為后續(xù)的深入學(xué)習(xí)打下堅(jiān)實(shí)的基礎(chǔ)。

          另外,我特意為大家創(chuàng)建了「技術(shù)交流群」,群里氛圍真的很不錯(cuò),希望能給需要的 同學(xué)再多一點(diǎn)幫助。掃描下方我的二維碼,回復(fù)「Java」我拉你入群。

          示例代碼已經(jīng)同步到 GitHub,地址為 github.com/itwanger,也可以點(diǎn)擊閱讀原文進(jìn)行跳轉(zhuǎn),歡迎 star。

          瀏覽 27
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜艹逼 | TS人妖系列自慰 | 久久蜜桃成人 | www.色婷婷五月综合在线色吧 | 大香蕉一人在线网 |