1. 程式人生 > >04.類(Class)與 物件(Object)

04.類(Class)與 物件(Object)

類屬於抽象的概念集合;

如汽車、輪船、書描述的都是某一類事物的公共特徵。

物件:表示一個個具體的事物
例如:張三同學、李四賬戶、王五的汽車,這些都是可以使用的事物, 就可以理解為物件, 所以物件表示的是一個個獨立的個體。
 

類與物件的基本定義

Class 類名稱 {
     //宣告成員變數
     資料型別  屬性(變數);
     
     ......
   
     //定義方法的內容
     public 返回值的資料型別  方法名稱(引數1,引數2,...){
            
           程式語句;
           
           [return 表示式]; 
    }
}

類中的屬性在開發中不一定只是變數,也有可能是其他內容,所以一般也會有人將其
稱為成員(Field),在Java中使用的就是“ Field” 單詞來描述的。

範例:定義類

class Book{
    String title;
    double price;
    public void getInfo(){//此方法將由物件呼叫
        System.out.println("圖書名稱:"+title+price);
    }
}
public class TestOo {
    public static void main(String args[]){
          Book bk=null;//宣告物件
          bk.title="Java開發";//操作屬性內容
          bk.price=89.9;
          bk.getInfo(); //呼叫類中的getInfo()方法
    }
}

此時根據給定的語法已經定義了一個Book 類, 在這個類中定義了兩個屬性: 圖書名稱( title 、
String型別) 、價格( price、double型別), 以及一個取得圖書完整資訊的getlnfo()方法。

為什麼Book類定義的getlnfo()方法沒有加上static?

在主類中定義, 並且由主方法直接呼叫的
方法必須加上static”, 但是現在的情況有些改變, 因為Book類的getlnfo()方法將會由對
象呼叫, 與之前的呼叫形式不同, 所以暫時沒有加上。

類定義完成後, 肯定無法直接使用, 如果要使用, 必須依靠物件, 由於類屬於引用資料型別, 所以
物件的產生格式如下。

格式:宣告並例項化物件。

類名稱 物件名稱=new 類名稱();

格式:分步完成。

宣告物件: 類名稱 物件名稱=null;
例項化物件: 物件名稱=new 類名稱();

當一個物件例項化後就可以按照如下方式利用物件來操作類的結構。
     物件屬性:表示要操作類中的屬性內容;
     物件方法:表示要呼叫類中的方法。

範例:使用類一一在主類中使用Book類。

class Book  { //定義一個新的類
    private String title;
    private double price;
    public void setTitle(String t){
        title=t;

    }
    public void setPrice(double p){
        if (p>0.0){
            price=p;
        }
    }
    public String getTitle(){
        return title;
    }
    public double getPrice(){
       return price;
    }
    public void getInfo(){
          System.out.println("圖書名稱:"+title+price);
    }
    public class TestOo{
        public static void main(String args[]){
            Book bk=null;//宣告物件
            bk.title="Java開發";//操作屬性內容
            bk.price=89.9;
            bk.getInfo(); //呼叫類中的getInfo()方法
    }
}
}
//檢查錯誤程式碼應該在setter之中增加,getter只是簡單的返回資料

類本身屬於引用資料型別, 而對於引用資料型別的
執行分析就必須結合記憶體操作來看

堆記憶體( heap)儲存每一個物件的屬性內容, 堆記憶體需要用關鍵字new才可以開闢, 如果一個
物件沒有對應的記憶體指向, 將無法使用;

棧記憶體( stack )儲存的是一塊堆記憶體的地址數值, 可以把它想象成一個int型變數(每一個int
型變數只能存放-個數值), 所以每一塊
記憶體只能夠保留一塊堆記憶體地址。

• 堆記憶體:儲存物件的真正資料, 都是每一個物件的屬性內容;
• 棧記憶體:儲存的是一塊堆記憶體的空間地址, 但是為了方便理解, 可以簡單地
將植記憶體中儲存的資料理解為物件的名稱(Book bk), 就假設儲存的是 “ bk” 物件
名稱。

物件使用前都需要進行例項化操作, 如果只是聲明瞭物件, 但是並沒有為其例項化,

會出現“ NullPointerException” (空指向異常)。

 

引用資料的初步分析

引用傳遞是整個Java中的精髓所在, 而引用傳遞的核心概念也只有一點: 一塊
堆記憶體空間(儲存物件的屬性資訊)可以同時被多個枝記憶體共同指向,則每一個戰
記憶體都可以修改同一塊堆記憶體空間的屬性值。

在所有的引用分析裡面,最關鍵的還是關鍵字“new”。一定要注意的是,每一次使用關鍵字new
都一定會開闢新的堆記憶體空間,所以如果在程式碼裡面宣告兩個物件,並且使用了關鍵字new為兩個物件
分別進行物件的例項化操作,那麼一定是各自佔有各自的堆記憶體空間,並且不會互相影響。

範例 :物件引用傳遞。

public class TestOo2{
    public static void mian(String args[]){
          Book bookA=new Book();
              Book bookB=null;
              bookA.title="java";
              bookA.price=80;
              bookB=bookA;//引用傳遞
              bookB.price=40;//利用第二個物件設定屬性內容
              bookA.getInfo();
    }
}

範例:深入觀察引用傳遞。

public class TestOo2{
    public static void mian(String args[]){
          Book bookA=new Book();
              Book bookB=new Book();
              bookA.title="java";
              bookA.price=10;
              bookB.title="jsp";
              bookB.price=20;
              bookB=bookA;//引用傳遞
              bookB.price=30;//利用第二個物件設定屬性內容
    }
}

本程式首先分別例項化了bookA 與bookB 兩個不同的物件,由於其儲存在不同的記憶體空間,
所以設定屬性時不會互相影響。然後發生了引用傳遞( bookB = bookA ),由於bookB 物件原本存
在有指向的堆記憶體空間,並且一塊棧記憶體只能夠儲存一塊堆記憶體空間的地址,所以bookB 要先斷開
已有的堆記憶體空間,再去指向book A 對應的堆記憶體空間, 這個時候對於原本的bookB 記憶體沒有任
何指向, bookB 將成為垃圾空間。最後由於bookB 物件修改了price 屬性的內容。程式的記憶體關係

通過記憶體分析可以發現,在引用資料型別關係時, 一塊沒有任何棧記憶體指向的堆記憶體空間將成
為垃圾,所有的垃圾會不定期地被垃圾收集器( Garbage Collector )問收, 回收後會被釋放掉其所
佔用的空間。
雖然Java 支援自動的垃圾收集處理. 但是在程式碼的開發過程中應該儘量減少垃圾空間的產生。