第二十三章 面向對象思想
作者:張子默
一、面向對象思想概述
1、概述
Java語言是一種面向對象的程序設計語言,而面向對象思想是一種程序設計思想,我們在面向對象思想的指引下,使用Java語言去設計、開發計算機程序。這裏的對象泛指現實中一切事物,每種事物都具備自己的屬性和行爲。面向對象思想就是在計算機程序設計過程中,參照現實中事物,將事物的屬性特徵、行爲特徵抽象出來,描述成計算機事件的設計思想。它區別於面向過程思想,強調的是通過調用對象的行爲來實現功能,而不是自己一步步的去操作實現。
2、舉例
洗衣服
-
面向過程:把衣服脫下來→找一個盆→放點洗衣粉→加點水→浸泡十分鐘→揉一揉→清洗衣服→擰乾→晾起來
-
面向對象:把衣服脫下來→打開全自動洗衣機→扔衣服→按鈕→晾起來
區別
-
面向過程:強調步驟
-
面向對象:強調對象,這裏的對象就是洗衣機
3、特點
面向對象思想是一種更符合我們思考習慣的思想,它可以將複雜的事情簡單化,並將我們從執行者變成了指揮者。面向對象的語言中,包含了三大基本特徵,即封裝、繼承和多態。
二、類和對象
1、什麼是類
- 類是一組相關屬性和行爲的集合。可以看成是一類事物的模板,使用事物的屬性特徵和行爲特徵來描述該類事物。
現實中,描述一類事物:
-
**屬性:**事物的狀態信息
-
**行爲:**事物能夠做什麼
舉例:小貓
屬性:名字、體重、年齡、顏色。行爲:走、跑、叫。
2、什麼是對象
- 對象是一類事物的具體體現。對象是類的一個實例(對象並不是找個女朋友),必然具備該類事物的屬性和行爲。
現實中,一類事物的一個實例:一隻小貓
舉例:一隻小貓
屬性:Tom、5KG、2years、yellow。行爲:溜牆根走、蹦躂的跑、喵喵叫。
3、類與對象的關係
-
類是對一類事物的描述,是抽象的。
-
對象是一類事物的實例,是具體的。
-
類是對象的模板,對象是類的實體。
三、類的定義
1、事物與類的對比
現實世界的一類事物:
**屬性:**事物的狀態信息。**行爲:**事物能否做什麼。
Java中用class描述事物也是如此:
成員變量:對應事物的屬性 成員方法:對應事物的行爲
2、類的定義格式
public class ClassName {
//成員變量
//成員方法
}
-
定義類就是定義類的成員,包括成員變量和成員方法。
-
成員變量和以前定義變量幾乎是一樣的。只不過位置發生了改變。在類中,方法外。
-
成員方法和以前定義方法幾乎是一樣的。只不過**把static去掉,**static的作用在面向對象後面章節中再做詳細講解。
類的定義格式舉例
/*
定義一個類,用來模擬"學生"事物,其中就有兩個組成部分
屬性(是什麼)
姓名
年齡
行爲(能做什麼)
喫飯
睡覺
學習
對應到Java類當中
成員變量(屬性)
String name; //姓名
int age; //年齡
成員方法(行爲)
public void eat() {} //喫飯
public void sleep() {} //睡覺
public void study() {} //學習
*/
public class Student {
//成員變量
String name; //姓名
int age; //年齡
//成員方法
public void eat() {
System.out.println("喫飯飯!");
}
public void sleep() {
System.out.println("睡覺覺!");
}
public void study() {
System.out.println("學習!");
}
}
四、對象的使用
1、對象的使用格式
創建對象
類名 對象名 = new 類名();
使用對象訪問類中的成員
對象名.成員變量;
對象名.成員方法();
對象的使用格式舉例
public class Test01_Student {
public static void main(String[] args) {
//創建對象格式:類名 對象名 = new 類名();
Student s = new Student();
System.out.println("s:"+s); //cn.itcast.Student@100363
//直接輸出成員變量值
System.out.println("姓名:"+s.name); //null
System.out.println("年齡:"+s.age); //0
System.out.println("‐‐‐‐‐‐‐‐‐‐");
//給成員變量賦值
s.name = "趙麗穎";
s.age = 18;
//再次輸出成員變量的值
System.out.println("姓名:"+s.name); //趙麗穎
System.out.println("年齡:"+s.age); //18
System.out.println("‐‐‐‐‐‐‐‐‐‐");
//調用成員方法
s.study(); // "好好學習,天天向上"
s.eat(); // "學習餓了要喫飯"
}
}
2、成員變量的默認值
五、類與對象的練習
1、定義手機類
/*
定義一個類,用來模擬"手機"事物
屬性:品牌、價格、顏色
行爲:打電話、發短信
對應到類當中
成員變量(屬性)
String brand; //品牌
double price; //價格
String color; //顏色
成員方法(行爲)
public void call() {} //打電話
public void sendMessage() {} //羣發短信
*/
public class Phone {
//成員變量
String brand; //品牌
double price; //價格
String color; //顏色
//成員方法
public void call(String who) {
System.out.println("給" + who +"打電話!");
}
public void sendMessage() {
System.out.println("羣發短信!");
}
}
2、定義測試類
public class Demo03PhoneOne {
public static void main(String[] args) {
//根據Phone類創建一個名爲phone的對象
//格式:類名稱 對象名 = new 類名稱();
Phone one = new Phone();
System.out.println(one.brand); // null
System.out.println(one.price); // 0.0
System.out.println(one.color); // null
System.out.println("==========");
one.brand = "蘋果";
one.price = 8388.0;
one.color = "黑色";
System.out.println(one.brand); //蘋果
System.out.println(one.price); // 8388.0
System.out.println(one.color); //黑色
System.out.println("==========");
one.call("喬布斯");
one.sendMessage();
}
}
六、對象內存圖
1、一個對象調用一個方法內存圖
通過上圖我們可以理解,在棧內存中運行的方法,遵循"先進後出,後進先出"的原則。變量p指向堆內存中的空間,尋找方法信息,去執行該方法。
但是,這裏依然有問題存在。創建多個對象時,如果每個對象內部都保存一份方法信息,這就是非常浪費內存了,因爲所有對象的方法信息都是一樣的。那麼如何解決這個問題呢?請看如下圖解。
2、兩個對象調用同一方法內存圖
對象調用方法時,根據對象中方法標記(地址值),去類中尋找方法信息。這樣哪怕是多個對象,方法信息只保存一份,節約內存空間。
實例
public class Demo04PhoneTwo {
public static void main(String[] args) {
//根據Phone類創建一個名爲phone的對象
//格式:類名稱 對象名 = new 類名稱();
Phone one = new Phone();
System.out.println(one.brand); // null
System.out.println(one.price); // 0.0
System.out.println(one.color); // null
System.out.println("==========");
one.brand = "蘋果";
one.price = 8388.0;
one.color = "黑色";
System.out.println(one.brand); //蘋果
System.out.println(one.price); // 8388.0
System.out.println(one.color); //黑色
System.out.println("==========");
one.call("喬布斯"); //給喬布斯打電話
one.sendMessage(); //羣發短信
System.out.println("==========");
//根據Phone類創建一個名爲phone的對象
//格式:類名稱 對象名 = new 類名稱();
Phone two = new Phone();
System.out.println(two.brand); // null
System.out.println(two.price); // 0.0
System.out.println(two.color); // null
System.out.println("==========");
two.brand = "三星";
two.price = 5999.0;
two.color = "藍色";
System.out.println(two.brand); //三星
System.out.println(two.price); // 5999.0
System.out.println(two.color); //藍色
System.out.println("==========");
two.call("歐巴"); //給歐巴打電話
two.sendMessage(); //羣發短信
}
}
3、兩個引用指向同一個對象的內存圖
public class Demo05PhoneTwo {
public static void main(String[] args) {
//根據Phone類創建一個名爲phone的對象
//格式:類名稱 對象名 = new 類名稱();
Phone one = new Phone();
System.out.println(one.brand); // null
System.out.println(one.price); // 0.0
System.out.println(one.color); // null
System.out.println("==========");
one.brand = "蘋果";
one.price = 8388.0;
one.color = "黑色";
System.out.println(one.brand); //蘋果
System.out.println(one.price); // 8388.0
System.out.println(one.color); //黑色
System.out.println("==========");
one.call("喬布斯"); //給喬布斯打電話
one.sendMessage(); //羣發短信
System.out.println("==========");
Phone two = one;
System.out.println(two.brand); // null
System.out.println(two.price); // 0.0
System.out.println(two.color); // null
System.out.println("==========");
two.brand = "三星";
two.price = 5999.0;
two.color = "藍色";
System.out.println(two.brand); //三星
System.out.println(two.price); // 5999.0
System.out.println(two.color); //藍色
System.out.println("==========");
two.call("歐巴"); //給歐巴打電話
two.sendMessage(); //羣發短信
}
}
4、使用對象類型作爲方法參數
public class Demo06PhoneParam {
public static void main(String[] args) {
Phone one = new Phone();
one.brand = "蘋果";
one.price = 8388.0;
one.color = "土豪金";
method(one); //傳遞進去的參數其實就是地址值
}
public static void method(Phone param) {
System.out.println(param.brand); //蘋果
System.out.println(param.price); //8388.0
System.out.println(param.color); //土豪金
}
}
5、使用對象類型作爲方法返回值
public class Demo07PhoneReturn {
public static void main(String[] args) {
Phone two = getPhone();
System.out.println(two.brand); //蘋果
System.out.println(two.price); //8388.0
System.out.println(two.color); //玫瑰金
}
public static Phone getPhone() {
Phone one = new Phone();
one.brand = "蘋果";
one.price = 8388.0;
one.color = "玫瑰金";
return one;
}
}
七、成員變量和局部變量區別
變量根據定義位置的不同,我們給變量起了不同的名字。如下圖所示:
1、實例
/*
局部變量和成員變量
1、定義位置不一樣【重點】
局部變量:方法內部
成員變量:方法外部,直接寫在類當中
2、作用範圍不一樣【重點】
局部變量:只有在方法當中纔可以使用,出了方法就不能再用
成員變量:整個類全都可以用
3、默認值不一樣【重點】
局部變量:沒有默認值,如果想要使用,必須手動進行賦值
成員變量:如果沒有賦值,會有默認值,規則和數組一樣
4、內存的爲止不一樣(瞭解)
局部變量:位於棧內存
成員變量:位於堆內存
5、生命週期不一樣(瞭解)
局部變量:隨着方法進棧而誕生,隨着方法出棧而消失
成員變量:隨着對象創建而誕生,隨着對象被垃圾回收而消失
*/
public class Demo08VariableDifference {
String name; //成員變量
public void methodA() {
int num = 20; //局部變量
System.out.println(num);
}
public void methodB(int param) { //方法的參數是局部變量
//參數在方法調用的時候,必然會被賦值
System.out.println(param);
int age;
//System.out.println(age); //錯誤寫法,沒賦值不能用
//System.out.println(num); //錯誤寫法
System.out.println(name);
}
}