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 支援自動的垃圾收集處理. 但是在程式碼的開發過程中應該儘量減少垃圾空間的產生。