日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java中this_夯实Java基础系列7:一文读懂Java 代码块和执行顺序

發(fā)布時間:2025/3/15 java 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中this_夯实Java基础系列7:一文读懂Java 代码块和执行顺序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • #java中的構(gòu)造方法 #構(gòu)造方法簡介 #構(gòu)造方法實例 #例-1 #例-2
  • #java中的幾種構(gòu)造方法詳解 #普通構(gòu)造方法 #默認構(gòu)造方法 #重載構(gòu)造方法 #java子類構(gòu)造方法調(diào)用父類構(gòu)造方法
  • #java中的代碼塊簡介
  • #java代碼塊使用 #局部代碼塊 #構(gòu)造代碼塊 #靜態(tài)代碼塊
  • #java代碼塊、構(gòu)造方法(包含繼承關(guān)系)的執(zhí)行順序
  • #參考文章
  • #微信公眾號 #java技術(shù)江湖 #個人公眾號:黃小斜

本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內(nèi)容請到我的倉庫里查看

https://github.com/h2pl/Java-Tutorial

喜歡的話麻煩點下Star哈

文章首發(fā)于我的個人博客:

www.how2playlife.com

本文是微信公眾號【Java技術(shù)江湖】的《夯實Java基礎(chǔ)系列博文》其中一篇,本文部分內(nèi)容來源于網(wǎng)絡(luò),為了把本文主題講得清晰透徹,也整合了很多我認為不錯的技術(shù)博客內(nèi)容,引用其中了一些比較好的博客文章,如有侵權(quán),請聯(lián)系作者。該系列博文會告訴你如何從入門到進階,一步步地學(xué)習(xí)Java基礎(chǔ)知識,并上手進行實戰(zhàn),接著了解每個Java知識點背后的實現(xiàn)原理,更完整地了解整個Java技術(shù)體系,形成自己的知識框架。為了更好地總結(jié)和檢驗?zāi)愕膶W(xué)習(xí)成果,本系列文章也會提供每個知識點對應(yīng)的面試題以及參考答案。

如果對本系列文章有什么建議,或者是有什么疑問的話,也可以關(guān)注公眾號【Java技術(shù)江湖】聯(lián)系作者,歡迎你參與本系列博文的創(chuàng)作和修訂。

Java中的構(gòu)造方法

構(gòu)造方法簡介

構(gòu)造方法是類的一種特殊方法,用來初始化類的一個新的對象。http://c.biancheng.net/java/ 中的每個類都有一個默認的構(gòu)造方法,它必須具有和類名相同的名稱,而且沒有返回類型。構(gòu)造方法的默認返回類型就是對象類型本身,并且構(gòu)造方法不能被 static、final、synchronized、abstract 和 native 修飾。

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

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

class class_name{public class_name(){} //默認無參構(gòu)造方法public ciass_name([paramList]){} //定義構(gòu)造方法…//類主體}

在一個類中,與類名相同的方法就是構(gòu)造方法。每個類可以具有多個構(gòu)造方法,但要求它們各自包含不同的方法參數(shù)。

構(gòu)造方法實例

例 1

構(gòu)造方法主要有無參構(gòu)造方法和有參構(gòu)造方法兩種,示例如下:

public class MyClass{private int m; //定義私有變量MyClass(){//定義無參的構(gòu)造方法m=0;}MyCiass(int m){//定義有參的構(gòu)造方法this.m=m;}}

該示例定義了兩個構(gòu)造方法,分別是無參構(gòu)造方法和有參構(gòu)造方法。在一個類中定義多個具有不同參數(shù)的同名方法,這就是方法的重載。這兩個構(gòu)造方法的名稱都與類名相同,均為 MyClass。在實例化該類時可以調(diào)用不同的構(gòu)造方法進行初始化。

注意:類的構(gòu)造方法不是要求必須定義的。如果在類中沒有定義任何一個構(gòu)造方法,則 Java 會自動為該類生成一個默認的構(gòu)造方法。默認的構(gòu)造方法不包含任何參數(shù),并且方法體為空。如果類中顯式地定義了一個或多個構(gòu)造方法,則 Java 不再提供默認構(gòu)造方法。

例 2

要在不同的條件下使用不同的初始化行為創(chuàng)建類的對象,這時候就需要在一個類中創(chuàng)建多個構(gòu)造方法。下面通過一個示例來演示構(gòu)造方法的使用。

(1) 首先在員工類 Worker 中定義兩個構(gòu)造方法,代碼如下:

public class Worker{public String name; //姓名private int age; //年齡//定義帶有一個參數(shù)的構(gòu)造方法public Worker(String name){this.name=name;}//定義帶有兩個參數(shù)的構(gòu)造方法public Worker(String name,int age){this.name=name;this.age=age;}public String toString(){return"大家好!我是新來的員工,我叫"+name+",今年"+age+"歲。";}}

在 Worker 類中定義了兩個屬性,其中 name 屬性不可改變。分別定義了帶有一個參數(shù)和帶有兩個參數(shù)的構(gòu)造方法,并對其屬性進行初始化。最后定義了該類的 toString() 方法,返回一條新進員工的介紹語句。

提示:Object 類具有一個 toString() 方法,該方法是個特殊的方法,創(chuàng)建的每個類都會繼承該方法,它返回一個 String 類型的字符串。如果一個類中定義了該方法,則在調(diào)用該類對象時,將會自動調(diào)用該類對象的 toString() 方法返回一個字符串,然后使用“System.out.println(對象名)”就可以將返回的字符串內(nèi)容打印出來。

(2) 在 TestWorker 類中創(chuàng)建 main() 方法作為程序的入口處,在 main() 方法中調(diào)用不同的構(gòu)造方法實例化 Worker 對象,并對該對象中的屬性進行初始化,代碼如下:

public class TestWorker{public static void main(String[] args){System.out.println("-----------帶有一個參數(shù)的構(gòu)造方法-----------");//調(diào)用帶有一個參數(shù)的構(gòu)造方法,Staff類中的sex和age屬性值不變Worker worker1=new Worker("張強");System.out.println(worker1);System.out.println("-----------帶有兩個參數(shù)的構(gòu)造方法------------");//調(diào)用帶有兩個參數(shù)的構(gòu)造方法,Staff類中的sex屬性值不變Worker worker2=new Worker("李麗",25);System.out.println(worker2);}}

在上述代碼中,創(chuàng)建了兩個不同的 Worker 對象:一個是姓名為張強的員工對象,一個是姓名為李麗、年齡為 25 的員工對象。對于第一個 Worker 對象 Worker1,并未指定 age 屬性值,因此程序會將其值采用默認值 0。對于第二個 Worker 對象 Worker2,分別對其指定了 name 屬性值和 age 屬性值,因此程序會將傳遞的參數(shù)值重新賦值給 Worker 類中的屬性值。

運行 TestWorker 類,輸出的結(jié)果如下:

-----------帶有一個參數(shù)的構(gòu)造方法-----------大家好!我是新來的員工,我叫張強,今年0歲。-----------帶有兩個參數(shù)的構(gòu)造方法------------大家好!我是新來的員工,我叫李麗,今年25歲。

通過調(diào)用帶參數(shù)的構(gòu)造方法,在創(chuàng)建對象時,一并完成了對象成員的初始化工作,簡化了對象初始化的代碼。

Java中的幾種構(gòu)造方法詳解

普通構(gòu)造方法

方法名與類名相同

無返回類型

子類不能繼承父類的構(gòu)造方法

不能被static、final、abstract修飾(有final和static修飾的是不能被子類繼承的,abstract修飾的是抽象類,抽象類是不能實例化的,也就是不能new)

可以被private修飾,可以在本類里面實例化,但是外部不能實例化對象(注意!!!)

public class A{ int i=0; public A(){ i=2; } public A(int i){ this.i=i; }}

默認構(gòu)造方法

如果沒有任何的構(gòu)造方法,編譯時系統(tǒng)會自動添加一個默認無參構(gòu)造方法

隱含的默認構(gòu)造方法

public A(){}

顯示的默認構(gòu)造方法

public A(){ System.out.print("顯示的默認構(gòu)造方法") }

重載構(gòu)造方法

比如原本的類里的構(gòu)造方法是一個參數(shù)的,現(xiàn)在新建的對象是有三個參數(shù),此時就要重載構(gòu)造方法

當(dāng)一個類中有多個構(gòu)造方法,有可能會出現(xiàn)重復(fù)性操作,這時可以用this語句調(diào)用其他的構(gòu)造方法。

public class A{ private int age; private String name; public A(int age,String name){ this.age=age; this.name=name; } public A(int age){ this(age,"無名氏");//調(diào)用 A(int age,String name)構(gòu)造方法 } public A(){ this(1);//調(diào)用 A(int age)構(gòu)造方法 } public void setName(String name) {this.name=name;} public String getName() {return name;} public void setAge(int age) {this.age=age;} public int getAge() {return age;}}A a=new A(20,"周一");A b=new A(20);A c=new A();String name = a.getName();String name1 = b.getName();int age = c.getAge();System.out.println(name);System.out.println(name1);System.out.println(age);

java子類構(gòu)造方法調(diào)用父類構(gòu)造方法

首先父類構(gòu)造方法是絕對不能被子類繼承的。

子類構(gòu)造方法調(diào)用父類的構(gòu)造方法重點是:子類構(gòu)造方法無論如何都要調(diào)用父類的構(gòu)造方法。

子類構(gòu)造方法要么調(diào)用父類無參構(gòu)造方法(包括當(dāng)父類沒有構(gòu)造方法時。系統(tǒng)默認給的無參構(gòu)造方法),要么調(diào)用父類有參構(gòu)造方法。當(dāng)子類構(gòu)造方法調(diào)用父類無參構(gòu)造方法,一般都是默認不寫的,要寫的話就是super(),且要放在構(gòu)造方法的第一句。當(dāng)子類構(gòu)造方法要調(diào)用父類有參數(shù)的構(gòu)造方法,那么子類的構(gòu)造方法中必須要用super(參數(shù))調(diào)用父類構(gòu)造方法,且要放在構(gòu)造方法的第一句。

當(dāng)子類的構(gòu)造方法是無參構(gòu)造方法時,必須調(diào)用父類無參構(gòu)造方法。因為系統(tǒng)會自動找父類有沒有無參構(gòu)造方法,如果沒有的話系統(tǒng)會報錯:說父類沒有定義無參構(gòu)造方法。

當(dāng)子類構(gòu)造方法是有參構(gòu)造方法時,這時就會有兩種情況。第一種:子類構(gòu)造方法沒有寫super,也就是說你默認調(diào)用父類無參構(gòu)造方法,這樣的話就和子類是無參構(gòu)造方法一樣。

第二種:子類構(gòu)造方法有super(參數(shù))時,就是調(diào)用父類有參構(gòu)造方法,系統(tǒng)會找父類有沒有參數(shù)一致(參數(shù)數(shù)量,且類型順序要相同)的有參構(gòu)造方法,如果沒有的話,同樣也會報錯。

但是這里會遇到和重載構(gòu)造方法this一樣問題,一個參數(shù)的構(gòu)造方法可以調(diào)用多個參數(shù)構(gòu)造方法,沒有的參數(shù)給一個自己定義值也是可以的。

Java中的代碼塊簡介

在java中用{}括起來的稱為代碼塊,代碼塊可分為以下四種:

一.簡介

1.普通代碼塊:

類中方法的方法體

2.構(gòu)造代碼塊

構(gòu)造塊會在創(chuàng)建對象時被調(diào)用,每次創(chuàng)建時都會被調(diào)用,優(yōu)先于類構(gòu)造函數(shù)執(zhí)行。

3.靜態(tài)代碼塊:

用static{}包裹起來的代碼片段,只會執(zhí)行一次。靜態(tài)代碼塊優(yōu)先于構(gòu)造塊執(zhí)行。

4.同步代碼塊:

使用synchronized(){}包裹起來的代碼塊,在多線程環(huán)境下,對共享數(shù)據(jù)的讀寫操作是需要互斥進行的,否則會導(dǎo)致數(shù)據(jù)的不一致性。同步代碼塊需要寫在方法中。

二.靜態(tài)代碼塊和構(gòu)造代碼塊的異同點

相同點:都是JVM加載類后且在構(gòu)造函數(shù)執(zhí)行之前執(zhí)行,在類中可定義多個,一般在代碼塊中對一些static變量進行賦值。

不同點:靜態(tài)代碼塊在非靜態(tài)代碼塊之前執(zhí)行。靜態(tài)代碼塊只在第一次new時執(zhí)行一次,之后不在執(zhí)行。而非靜態(tài)代碼塊每new一次就執(zhí)行一次。

Java代碼塊使用

局部代碼塊

位置:局部位置(方法內(nèi)部)

作用:限定變量的生命周期,盡早釋放,節(jié)約內(nèi)存

調(diào)用:調(diào)用其所在的方法時執(zhí)行

?

public class 局部代碼塊 {@Testpublic void test (){ B b = new B(); b.go();}}class B { B(){} public void go() { //方法中的局部代碼塊,一般進行一次性地調(diào)用,調(diào)用完立刻釋放空間,避免在接下來的調(diào)用過程中占用??臻g //因為棧空間內(nèi)存是有限的,方法調(diào)用可能會會生成很多局部變量導(dǎo)致棧內(nèi)存不足。 //使用局部代碼塊可以避免這樣的情況發(fā)生。 { int i = 1; ArrayList list = new ArrayList<>(); while (i < 1000) { list.add(i ++); } for (Integer j : list) { System.out.println(j); } System.out.println("gogogo"); } System.out.println("hello"); }}

構(gòu)造代碼塊

位置:類成員的位置,就是類中方法之外的位置

作用:把多個構(gòu)造方法共同的部分提取出來,共用構(gòu)造代碼塊

調(diào)用:每次調(diào)用構(gòu)造方法時,都會優(yōu)先于構(gòu)造方法執(zhí)行,也就是每次new一個對象時自動調(diào)用,對 對象的初始化

class A{ int i = 1; int initValue;//成員變量的初始化交給代碼塊來完成 { //代碼塊的作用體現(xiàn)于此:在調(diào)用構(gòu)造方法之前,用某段代碼對成員變量進行初始化。 //而不是在構(gòu)造方法調(diào)用時再進行。一般用于將構(gòu)造方法的相同部分提取出來。 // for (int i = 0;i < 100;i ++) { initValue += i; } } { System.out.println(initValue); System.out.println(i);//此時會打印1 int i = 2;//代碼塊里的變量和成員變量不沖突,但會優(yōu)先使用代碼塊的變量 System.out.println(i);//此時打印2 //System.out.println(j);//提示非法向后引用,因為此時j的的初始化還沒開始。 // } { System.out.println("代碼塊運行"); } int j = 2; { System.out.println(j); System.out.println(i);//代碼塊中的變量運行后自動釋放,不會影響代碼塊之外的代碼 } A(){ System.out.println("構(gòu)造方法運行"); }}public class 構(gòu)造代碼塊 { @Test public void test() { A a = new A(); }}

靜態(tài)代碼塊

位置:類成員位置,用static修飾的代碼塊 作用:對類進行一些初始化 只加載一次,當(dāng)new多個對象時,只有第一次會調(diào)用靜態(tài)代碼塊,因為,靜態(tài)代碼塊 是屬于類的,所有對象共享一份 調(diào)用: new 一個對象時自動調(diào)用 public class 靜態(tài)代碼塊 {@Testpublic void test() { C c1 = new C(); C c2 = new C(); //結(jié)果,靜態(tài)代碼塊只會調(diào)用一次,類的所有對象共享該代碼塊 //一般用于類的全局信息初始化 //靜態(tài)代碼塊調(diào)用 //代碼塊調(diào)用 //構(gòu)造方法調(diào)用 //代碼塊調(diào)用 //構(gòu)造方法調(diào)用}}class C{ C(){ System.out.println("構(gòu)造方法調(diào)用"); } { System.out.println("代碼塊調(diào)用"); } static { System.out.println("靜態(tài)代碼塊調(diào)用"); }}

Java代碼塊、構(gòu)造方法(包含繼承關(guān)系)的執(zhí)行順序

這是一道常見的面試題,要回答這個問題,先看看這個實例吧。

一共3個類:A、B、C其中A是B的父類,C無繼承僅作為輸出

A類:

public class A {static { Log.i("HIDETAG", "A靜態(tài)代碼塊");}private static C c = new C("A靜態(tài)成員");private C c1 = new C("A成員");{ Log.i("HIDETAG", "A代碼塊");}static { Log.i("HIDETAG", "A靜態(tài)代碼塊2");}public A() { Log.i("HIDETAG", "A構(gòu)造方法");}}

B類:

public class B extends A {private static C c1 = new C("B靜態(tài)成員");{ Log.i("HIDETAG", "B代碼塊");}private C c = new C("B成員");static { Log.i("HIDETAG", "B靜態(tài)代碼塊2");}static { Log.i("HIDETAG", "B靜態(tài)代碼塊");}public B() { Log.i("HIDETAG", "B構(gòu)造方法");}}

C類:

public class C {public C(String str) { Log.i("HIDETAG", str + "構(gòu)造方法");}}

執(zhí)行語句:new B();

輸出結(jié)果如下:

I/HIDETAG: A靜態(tài)代碼塊 I/HIDETAG: A靜態(tài)成員構(gòu)造方法 I/HIDETAG: A靜態(tài)代碼塊2 I/HIDETAG: B靜態(tài)成員構(gòu)造方法 I/HIDETAG: B靜態(tài)代碼塊2 I/HIDETAG: B靜態(tài)代碼塊 I/HIDETAG: A成員構(gòu)造方法 I/HIDETAG: A代碼塊 I/HIDETAG: A構(gòu)造方法 I/HIDETAG: B代碼塊 I/HIDETAG: B成員構(gòu)造方法 I/HIDETAG: B構(gòu)造方法

得出結(jié)論:

執(zhí)行順序依次為:父類的靜態(tài)成員和代碼塊子類靜態(tài)成員和代碼塊父類成員初始化和代碼快父類構(gòu)造方法子類成員初始化和代碼塊子類構(gòu)造方法

注意:可以發(fā)現(xiàn),同一級別的代碼塊和成員初始化是按照代碼順序從上到下依次執(zhí)行

看完上面這個demo,再來看看下面這道題,看看你搞得定嗎?

看下面一段代碼,求執(zhí)行順序:

class A { public A() { System.out.println("1A類的構(gòu)造方法"); } { System.out.println("2A類的構(gòu)造快"); } static { System.out.println("3A類的靜態(tài)塊"); }} public class B extends A { public B() { System.out.println("4B類的構(gòu)造方法"); } { System.out.println("5B類的構(gòu)造快"); } static { System.out.println("6B類的靜態(tài)塊"); } public static void main(String[] args) { System.out.println("7"); new B(); new B(); System.out.println("8"); }}

執(zhí)行順序結(jié)果為:367215421548

為什么呢?

首先我們要知道下面這5點:

每次new都會執(zhí)行構(gòu)造方法以及構(gòu)造塊。構(gòu)造塊的內(nèi)容會在構(gòu)造方法之前執(zhí)行。非主類的靜態(tài)塊會在類加載時,構(gòu)造方法和構(gòu)造塊之前執(zhí)行,切只執(zhí)行一次。主類(public class)里的靜態(tài)塊會先于main執(zhí)行。繼承中,子類實例化,會先執(zhí)行父類的構(gòu)造方法,產(chǎn)生父類對象,再調(diào)用子類構(gòu)造方法。所以題目里,由于主類B繼承A,所以會先加載A,所以第一個執(zhí)行的是第3句。

從第4點我們知道6會在7之前執(zhí)行,所以前三句是367。

之后實例化了B兩次,每次都會先實例化他的父類A,然后再實例化B,而根據(jù)第1、2、5點,知道順序為2154。

最后執(zhí)行8

所以順序是367215421548

參考文章

https://blog.csdn.net/likunkun__/article/details/83066062https://www.jianshu.com/p/6877aae403f7https://www.jianshu.com/p/49e45af288eahttps://blog.csdn.net/du_du1/article/details/91383128http://c.biancheng.net/view/976.htmlhttps://blog.csdn.net/evilcry2012/article/details/79499786https://www.jb51.net/article/129990.htm

微信公眾號

Java技術(shù)江湖

如果大家想要實時關(guān)注我更新的文章以及分享的干貨的話,可以關(guān)注我的公眾號【Java技術(shù)江湖】一位阿里 Java 工程師的技術(shù)小站,作者黃小斜,專注 Java 相關(guān)技術(shù):SSM、SpringBoot、MySQL、分布式、中間件、集群、Linux、網(wǎng)絡(luò)、多線程,偶爾講點Docker、ELK,同時也分享技術(shù)干貨和學(xué)習(xí)經(jīng)驗,致力于Java全棧開發(fā)!

Java工程師必備學(xué)習(xí)資源: 一些Java工程師常用學(xué)習(xí)資源,關(guān)注公眾號后,后臺回復(fù)關(guān)鍵字 “Java” 即可免費無套路獲取。

個人公眾號:黃小斜

作者是 985 碩士,螞蟻金服 JAVA 工程師,專注于 JAVA 后端技術(shù)棧:SpringBoot、MySQL、分布式、中間件、微服務(wù),同時也懂點投資理財,偶爾講點算法和計算機理論基礎(chǔ),堅持學(xué)習(xí)和寫作,相信終身學(xué)習(xí)的力量!

程序員3T技術(shù)學(xué)習(xí)資源: 一些程序員學(xué)習(xí)技術(shù)的資源大禮包,關(guān)注公眾號后,后臺回復(fù)關(guān)鍵字 “資料” 即可免費無套路獲取。

總結(jié)

以上是生活随笔為你收集整理的java中this_夯实Java基础系列7:一文读懂Java 代码块和执行顺序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。