1. 程式人生 > >[03] 類的結構和創建對象

[03] 類的結構和創建對象

是否 ava 字節 ati 成員變量 ++ 調用構造 syn span


1、類的結構和定義

先回顧一下,類的基本概念:
  • 類定義了對象共同的屬性和行為(即方法)
  • 具體的某個對象需要通過類來進行申明

那麽顯而易見地,類中應該包含的東西就有,屬性、方法,另外,既然對象要通過類來聲明,那麽類中必須要有一個類似生產機器的東西來生成對象,這個類似生產機器的東西叫做構造函數。另外,類還可有內部類和塊,這兩種使用較少。
所以,類的結構內容就是:
  • 屬性(對象數據的描述)
  • 方法(對象的行為)
  • 構造函數(用於生產對象,也叫做實例化對象)
  • 內部類(在類體中申明的類)
  • (分為靜態塊、實例塊)

  1. public class Person {
  2. //屬性
  3. String name;
  4. int age;
  5. //方法
  6. public void eat() {
  7. System.out.println("吃東西");
  8. }
  9. public void run() {
  10. System.out.println("跑起來");
  11. }
  12. //構造方法
  13. public Person() {
  14. }
  15. //塊
  16. {
  17. System.out.println("我是實例塊");
  18. }
  19. static {
  20. System.out.println("我是靜態塊");
  21. }
  22. //內部類
  23. class InnerClass{
  24. }
  25. }

1.1 類的申明

  1. 【訪問權限修飾符】【修飾符】class 類名 {
  2. 類體
  3. }
  4. //【】中的內容表示可選項
  5. e.g.
  6. public class Person {
  7. ...
  8. }
  • 類的命名規範:首字母大寫,之後的單詞首字母才大寫,其余小寫
  • 訪問權限修飾符:default、private、protected、public(default即什麽都不寫)
  • 修飾符:final、synchronized、abstract
  • 訪問權限修飾符和修飾符在之後說明,本章不做說明

1.2 屬性的申明

  1. 【訪問權限修飾符】【修飾符】數據類型 屬性名【=初值】;
  2. //【】中的內容表示可選項
  3. e.g.
  4. private String name;
  5. private
    double salary;
  6. private static int count = 0;
  • 屬性的命名規則:小寫,多個單詞則後面的單詞首字母大寫
  • 註意:屬性又稱為成員變量,是聲明在類中的變量,方法體中聲明的變量稱為局部變量或臨時變量

1.3 方法

1.3.1 方法的申明

  1. 【訪問權限修飾符】【修飾符】返回值數據類型 方法名(形式參數列表) {
  2. 執行語句;
  3. return 返回值;
  4. }
  5. //【】中的內容表示可選項
  6. e.g.
  7. public String eat(String food){
  8. return "吃" + food;
  9. }
  10. public void eat(){
  11. System.out.println("吃東西");
  12. }
  • 方法命名規範:小寫,多個單詞則後面的單詞首字母大寫
  • 返回值類型必須填寫,如果沒有類型也需要填寫void(如果是void則不需要return語句)

1.3.2 方法中的部分概念解釋

方法,其實就是定義在類中具有特定功能的一段獨立小程序,更多時候我們稱之為函數。
形式參數,就是一個變量,用來傳遞給方法進行使用,就像 public String eat(String food){ ... },某個人要執行吃的行為,那得遞給他食物他才能行動呀,所以這裏的食物,就是吃這個方法的參數。
返回值,即如果你關心並希望得到這個方法的執行結果,那麽需要規定返回值的數據類型,再使用return語句把結果告訴你。如果你只是進行一些操作,不關心最終的結果,就像你只想執行吃飯的操作,你不關心最終吃沒吃飽,那麽就意味著沒有返回值,那麽返回值數據類型就填寫void,也沒有return語句。

1.3.3 方法的特點

  • 定義方法可以將功能代碼進行封裝
  • 方法可以復用
  • 方法只有被調用時才會執行
  • 方法中可以調用其它方法,但是不可能在方法內部定義方法

1.3.4 方法重載

如果在一個類中,需要實現兩個整數求和,兩個浮點數求和,這兩個方法如何定義?1、定義兩個方法,分別命名為addInt、addDouble2、定義一個方法,叫add,但形參數據類型不同
顯然,使用後者更為適宜,所以在Java中,如果有多個同名但是不同參數的方法,我們稱之為“方法重載”,編譯器會根據調用時傳遞的實際參數自動判斷具體調用的是哪個重載方法。
  1. e.g.
  2. int add(int x, int y){...}
  3. float add(float x, float y){...}
  4. double add(double x, double y){...}

所謂的不同參數,是指參數的:
  • 數量不同
  • 類型不同
  • 順序不同

值得一提的是,方法重載跟方法的返回值類型沒有任何關系,也就是說,如果只是返回值不同的方法,不能構成重載。
  1. //錯誤的方法重載
  2. void fun(int x){...}
  3. int fun(int x){...}

1.4 構造方法

  1. 【訪問權限修飾符】類名(形式參數列表){
  2. 方法體
  3. }
  4. //【】中的內容表示可選項
  • 構造方法的名稱必須和類名相同
  • 構造方法也有方法重載
  • 構造方法中也可以編寫復雜程序,但是一般只用於定義屬性,即初始化對象屬性

那麽問題來了:構造方法是用來聲明類的,那麽為什麽我們有時候不寫構造方法,依然可以進行實例化?
那麽答案來了:任何類都有一個默認的無參的構造方法,只有在你自定義了某個構造方法後,這個默認的無參構造方法才會失效。


2、創建對象

2.1 實例化對象

使用new調用構造方法,創建類的一個對象:
  1. //調用無參數的構造方法
  2. 類名 對象名 = new 該類的構造方法();
  3. e.g. Book javaBook = new Book();
  4. //調用有參數的構造方法
  5. 類名 對象名 = new 該類的構造方法(參數1, 參數2...);
  6. e.g. Book javaBook = new Book("西遊記");

使用對象,可以使用 “.” 進行以下操作:
  • 訪問類的屬性:對象名.屬性
  • 調用類的方法:對象名.方法名()
  1. e.g.
  2. javaBook.name = "東遊記";
  3. javaBook.borrow();

2.2 實例化對象的過程

假設存在一個類Person,創建對象語句如下:
  1. Person zhangsan = new Person();

將上面的語句分為兩個步驟:
  1. Person zhangsan;
  2. zhangsan = new Person();

即,實例化一個對象後,其實有兩個實體:
  • 對象引用變量,在棧空間,即zhangsan,稱之為引用,或句柄,存放的是對象的虛地址
  • 對象本身,即使用new Person()在堆空間裏創建的實體,將對象的屬性值存儲在堆裏
  • 可以使用引用變量操作對象的屬性和方法

意思類似於旅館的房間和鑰匙:
  • 當你使用new時,就相當於在旅館前臺說你要開個房間,那麽前臺會給你一把鑰匙,就是這裏的引用變量,如上例的zhangsan
  • 鑰匙指向房間,所以有了鑰匙你就能找到房間,才能對房間進行布置

  1. public class Room {
  2. private String bed;
  3. private String lamp;
  4. public Room(String bed, String lamp) {
  5. this.bed = bed;
  6. this.lamp = lamp;
  7. }
  8. public String getBed() {
  9. return bed;
  10. }
  11. public void setBed(String bed) {
  12. this.bed = bed;
  13. }
  14. public String getLamp() {
  15. return lamp;
  16. }
  17. public void setLamp(String lamp) {
  18. this.lamp = lamp;
  19. }
  20. public static void main(String[] args) {
  21. Room room1 = new Room("單人大床", "小燈");
  22. Room room2 = new Room("雙人大床", "大燈");
  23. }
  24. }
如上例:1、把Room類的字節碼加載到內存2、根據Room類的申明,把屬性bed、lamp初始化到內存堆,並賦默認值,String的默認值為null3、根據代碼,調用兩個參數的構造方法,把"單人大床"和"小燈"分別賦值給bed和lamp4、在棧中創建一個變量room1,用來引用堆中的對象,room1的值是一個16進制的數,表示一個虛地址5、重復2-4創建room2,room2和room1是不同的引用,指向不同的具體對象


3、塊與內部類

塊在類中申明,類似一個沒有方法申明的方法體,分實例塊和靜態塊。

3.1 塊

3.1.1 實例塊

顧名思義,屬於某個具體的對象,所以會在每次調用構造方法之前自動調用
  1. {
  2. //任何符合語法的Java代碼
  3. }

3.1.2 靜態塊

在類加載時被調用一次,僅一次,與是否創建對象無關
  1. static {
  2. //任何符合語法的Java代碼
  3. }

3.2 內部類

將一個類的定義放到另一個類中,就是內部類。
  1. public class Outer{
  2. private int x;
  3. class Inner{
  4. public test(){
  5. x++;
  6. }
  7. }
  8. }

內部類對於初學者使用很少,這裏不再詳細闡述了,可以參考:
  • java提高篇(八)----詳解內部類
  • Java 中引入內部類的意義?



[03] 類的結構和創建對象