南陽做網站百度搜索引擎排名規(guī)則
構造方法
接上篇,若每次都想下面的setDate方法給對象初始化,未免比較麻煩,那有什么方法可以讓初始化更加簡便呢?
public void setDate(int year, int month, int day){this.year = year;this.month = month;this.day = day;}
答:使用構造方法
概念
構造方法是一個特殊的成員方法,名字必須與類名相同(沒有返回值,設置為void也不行),在創(chuàng)建對象時,由編譯器自動調用,并且在整個對象的生命周期內只調用一次。
方法名 (形參列表){//方法名須與類名相同方法體
}
小拓展:一個對象生成至少有兩步:
- 為對象分配內存
- 調用合適的構造方法
構造方法的作用就是對對象中的成員進行初始化,并不負責給對象開辟空間,實例化時可以用構造方法對對象進行初始化
public Date(int year, int month, int day){this.year = year;this.month = month;this.day = day;}
對日期類可以做以上構造方法,這樣在實例化時就可以直接為對象進行初始化,初始化代碼如下
Date date = new Date(2004,12,20);
在寫構造方法時可以發(fā)生重載:下面代碼中即使兩個構造方法的類名一樣,但是參數不同,不會報錯,發(fā)生了方法的重載,想要調用哪個就可以調用哪個。
但是當沒有寫任何構造方法時,Java會提供一個默認不帶參數的構造方法(一旦寫了構造方法,Java就不會在提供不帶參數的構造方法),這也是我們不寫構造方法對象也能生成的原因。
public Date(){System.out.println("這個是不帶參數的構造方法");}public Date(int year, int month, int day){System.out.println("這個是帶有三個參數的構造方法");this.year = year;this.month = month;this.day = day;}
構造方法中可以使用this來調用其他構造方法:
注意事項:
- this( ) 必須是該構造方法中的第一條語句
- 格式是
this( 參數 )
- 不能形成環(huán)(像循環(huán)一樣調來調去的沒有意義)
以下是在沒有參數的Date構造方法中調用有參數的Date構造方法代碼
public Date(int year, int month, int day){System.out.println("這個是帶有三個參數的構造方法");this.year = year;this.month = month;this.day = day;}public Date(){this(2024,5,5);System.out.println("這個是不帶參數的構造方法");}
總結:
- 構造方法名必須與類名相同
- 構造方法沒有返回值類型,設置為void也不行
- 創(chuàng)建對象時由編譯器自動調用,并且在對象的生命周期內只調用一次(實例化對象時一定會調用構造方法)
- 構造方法可以重載(可以根據需求寫出不同的構造方法)
- 如果用戶沒有顯式定義(自己寫),編譯器會生成一份默認的構造方法,生成的默認構造方法一定是無參的(注意:一旦用戶定義,編譯器則不再生成)
- 當然,當我們自己寫的構造方法參數列表與實際實例化時參數列表個長度不同,由于編譯器不會再生成不帶參數的構造方法,所以編譯器報錯
- 絕大多數用public修飾,特殊情況下用private修飾
- 小技巧:idea中自動生成構造方法
封裝
面向對象程序三大特性:封裝、繼承、多態(tài)。(可能的誤區(qū):這三個不是哪個語言的特征,而是面向對象的特征)
什么是封裝?
封裝:將數據和操作數據的方法進行有機結合,隱藏對象的屬性和實現細節(jié),僅對外公開接口來和對象進行 交互
(套殼屏蔽細節(jié),用東西包裝起來對外隱藏內部實際細節(jié))
總的來說就是對成員變量和成員方法用private進行修飾。
達到的效果:就是該成員變量或成員方法只能在當前類內部使用,當前類外不能使用(可以寫一個方法只能供這個類內的方法使用,這樣類外就不知道這個只能供這個類內的方法是怎么寫的, 實現了隱藏)
訪問限定符(管當前修飾的字段或方法的訪問權限)
當一個字段或方法前沒有任何訪問限定符,則為默認權限 default
包
包的概念
在我們的電腦中,我們?yōu)榱朔诸?#xff0c;會把同一類的東西放到一個文件夾中,但是我們會發(fā)現一個文件夾中不能出現相同名字的文件或文件夾。
類似的,在Java中為了更好地管理類,把類聚集到一個包中,稱為軟件包。包是對類、接口等的封裝機制的體現,是一種對類或者接口等的很好的組織方式,像文件夾一樣,一個包中不能有名字相同的兩個類(但是在一個工程中可以有兩個名字相同的類,只要不在同一個包中)
導入包
Java 中已經提供了很多現成的類供我們使用,我們可以使用 import語句導入包比如說導入 java.util 這個包中的 Date 類
import java.util.Date;
如果想導入 java.util 這個包中的所有類可以 import java.util.*
但是同一個包中可能會有名字相同的類,所以建議顯式的指定要導入的類名,否則還是容易出現沖突的情況
import導入的是包下的所有類,用到這個包底下哪個類就回調用哪個(而不是導入的這個包)
/*java.lang:系統常用基礎類(String,Object),此包從JDK1.1后自動導入
java.lang.reflect:反射編程包
java.net:進行網絡編程開發(fā)包
java.sql:進行數據庫開發(fā)的支持包
java.util:Java提供的工具程序包(集合類等)非常重要
java.io:I/O編程開發(fā)包*/
可以使用import static導入包中靜態(tài)的方法和字段
import static java.lang.Math.*
用靜態(tài)導入包的好處是可以直接使用靜態(tài)成員而不用通過類名來訪問,使代碼更簡潔
注意事項: import 和 C++ 的 #include 差別很大. C++ 必須 #include 來引入其他文件內容, 但是 Java 不需要。import 只是為了寫代碼的時候更方便. import 更類似于 C++ 的 namespace 和 using
static
static修飾成員變量
static修飾的成員變量,稱為靜態(tài)成員變量,也叫類變量,靜態(tài)成員變量最大的特性:不屬于某個具體的對象,是所有對象所共享的
【靜態(tài)成員變量特性】
- 不屬于某個具體的對象,是類的屬性,所有對象共享的,不存儲在某個對象的空間中
- 既可以通過對象訪問,也可以通過類名訪問,但一般更推薦使用類名訪問
- 類變量只有一份且存儲在方法區(qū)當中
- 生命周期伴隨類的一生(即:隨類的加載(.class文件通過java文件轉化成class對象)而創(chuàng)建,隨類的卸載而銷毀)
- Java當中不允許定義局部的靜態(tài)變量(可以通過類名或通過對象的引用訪問,建議用類名訪問)(static修飾的變量是類變量而不是局部變量)
static修飾成員方法
被static修飾的成員方法稱為靜態(tài)成員方法,是類的方法,不是某個對象所特有的。靜態(tài)成員一般是通過靜態(tài)方法來訪問的
【靜態(tài)方法特性】
- 不屬于某個具體的對象,是類方法
- 可以通過對象調用,也可以通過==類名.靜態(tài)方法名(…)==方式調用,更推薦使用后者
- 不能在靜態(tài)方法中訪問任何非靜態(tài)成員變量
- == 靜態(tài)方法中不能直接調用任何非靜態(tài)方法,非靜態(tài)方法中可以調用靜態(tài)方法==,因為非靜態(tài)方法有this參數,在靜態(tài)方法中調用時候無法傳遞this引用(靜態(tài)方法中不能使用 static 關鍵字)
因為:靜態(tài)方法不依賴與對象,可以直接通過類名來訪問
但是:非靜態(tài)方法依賴于對象,要通過對象引用訪問
想要在靜態(tài)方法中調用非靜態(tài)方法需要先new對象,在通過對象引用訪問- 靜態(tài)方法無法重寫,不能用來實現多態(tài)
注意:靜態(tài)的不依賴于對象,屬于類,不屬于對象
static成員變量初始化
一般通過四種方式:
就地初始化
靜態(tài)代碼塊初始化(下面講)
構造方法(少)
get set 方法初始化
代碼塊
概念及分類
使用 {} 定義的一段代碼稱為代碼塊。分下面四種:
- 普通代碼塊:定義在方法中的代碼塊(一般不寫)
- 構造代碼塊:也叫實例代碼塊
- 靜態(tài)代碼塊:一般用來初始化靜態(tài)成員變量
static { }
- 同步代碼塊:未來再議
構造代碼塊:
//實例代碼塊/構造代碼塊{this.name = "z";//實例化對象this.age = 18;this.num = 11;}
靜態(tài)代碼塊:
//靜態(tài)代碼塊static {classname = 1;//靜態(tài)成員變量}
關于代碼塊:
- 靜態(tài)代碼塊在類加載的時候被執(zhí)行(靜態(tài)成員變量是類的屬性,因此是在JVM加載類時開辟空間并初始化的)
- 如果定義了多個靜態(tài)代碼塊/構造代碼塊,則執(zhí)行順序與定義順序有關
- 靜態(tài)代碼塊不管生成了多少個對象只會執(zhí)行一次->說明這個類只會被執(zhí)行一次
- 實例代碼塊只有在創(chuàng)建對象時才會執(zhí)行
關于代碼塊順序問題:
由于靜態(tài)代碼塊在加載時就執(zhí)行了,而實例代碼塊在創(chuàng)建對象時才會執(zhí)行,所以靜態(tài)代碼塊的執(zhí)行順序先與實例代碼塊
//實例代碼塊/構造代碼塊{this.name = "z";this.age = 18;this.num = 11;System.out.println("構造");}//靜態(tài)代碼塊static {classname = 1;System.out.println("靜態(tài)");}//構造代碼塊{this.name = "z";this.age = 18;this.num = 11;System.out.println("構造");}
上述代碼中,打印順序為下圖,由此可見靜態(tài)代碼塊執(zhí)行順序先與構造代碼塊
對象的打印
重新實現toString來打印對象,代碼如下
public class Person {public String name;public String gander;public int age;public Person(String name, String gander, int age){//構造方法this.name = name;this.gander = gander;this.age = age;}public String toString(){//重寫toStringreturn "[" + this.name + "," + this.gander + "," + this.age + "]";}public static void main(String[] args) {Person person = new Person("z","女",13);System.out.println(person);//打印時參數為對象名}
}