Java工程師培訓課(七)
夜光序言:
孤獨沒什麼不好,至少不必丟了驕傲
寂寞沒什麼不好,至少不必丟了尊嚴
一個人沒什麼不好,至少不必丟了自己
正文:
萬物皆物件
我們是怎麼認識世界的?
人類從小就不斷的接觸到各種各類存在世界上的各種生物,然後通過事物的公共特性,將它們歸類,所以以後就不會出現見到貓叫老虎。那麼我們在現實生活中,是通過具體的某個事物歸納總結它們的公共特性然後產生類那麼類就描述了該種事物的的共別。性,相當於造事物的圖紙,我們可以根據這個圖紙去做出具體的實體物件。
物件
類:實際就是對某種型別事物的共性屬性與行為的抽取。
人類認識世界: 物件----à類。
在java中: 類 -----à物件。
使用計算機語言就是不斷的在描述現實生活中的事物。
java中描述事物通過類的形式體現,類是具體事物的抽象,概念上的定義。
物件即是該類事物實實在在存在的個體。
類與物件的關係如圖
可以理解為:
類就是圖紙
汽車就是堆記憶體中的物件
面向物件的概述
“面向物件”(英語:Object Oriented,簡稱OO)是一種以事物為中心
面向物件程式設計(英語:Object-oriented programming,縮寫:OOP),是一種程式開發的方法。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充套件性。
面向物件時相對於面向過程而已的(c則是一個典型的面向過程的語言),站在面向物件的角度去看問題,你則是物件的動作的指揮者。如果站在面向過程的角度去看問題,你則是動作的執行者。
面向物件與面向過程對比
“萬物皆物件”。
1:買電腦
1:面向過程
1:查資料
2:電腦城砍價
3:被黑
4:痛苦歸來
1:面向物件
1:找物件。老師
2:老師.砍價
3:老師.檢測電腦
4:電腦成功購買
2:吃飯
1:面向過程
1:自己動手做
2:買菜
3:洗菜
4:煮飯炒菜
5:很難吃,浪費時間
2:面向物件
1:找專業物件
2:餐館.點餐
3:餐館,做飯
4:飯好吃,節約時間,精力
4:找物件
1:求介紹,相親,找現成的物件。(面向物件的思想先找有的物件,直 接拿來使用)
2:不滿意,沒有物件,自己造一個。(sun沒有提供,自己造物件)
再例如:人開門,人開電視,人畫園。
面向過程
強調的是功能行為,面向過程”是一種以過程為中心的程式設計思想。“面向過程”他們不支援豐富的“面向物件”特性(比如繼承、多型),就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,使用的時候一個一個依次呼叫就可以了。面向過程在這一系列工作的執行中,強調的是工作的執行。
物件
物件(object)代表現實世界中可以明確標識的一個實體。例如:一個學生、一張桌子、一間教室,一臺電腦都可以看做是一個物件。每個物件都有自己獨特的狀態標識和行為
物件的屬性(attribute,或者狀態(state)),學生有姓名和學號,該學生特有的姓名和學號就是該學生(物件)的屬性。
物件的行為(behavior),是由方法定義,呼叫物件的一個方法,其實就是給物件發訊息,要求物件完成一個動作。可以定義學生物件具備學習的行為。學生物件可以呼叫學習的方法,執行學習的動作
面向物件的特徵
封裝(encapsulation)
繼承(inheritance)
多型(polymorphism)
開發的過程:其實就是不斷的建立物件,使用物件,指揮物件做事情。
設計的過程:其實就是在管理和維護物件之間的關係.
使用java來描述事物
案例:通過Java語言定義一個汽車類,並生產出汽車,有顏色,輪胎個數, 有執行的功能。
分析:
如何描述現實世界中的事物,描述該事物的屬性和行為,汽車具有顏色和輪胎數的屬性,具備執行的行為。
如何使用Java語言進行轉換?
根據對應關係:
屬性:類中的成員變數
行為:類中的成員函式
那麼定義Java類就是定義一個類的成員。汽車類具備的成員是:顏色,輪胎數,執行方法。
Car類定義流程:
- 使用class 關鍵字 定義類,
-
-
- class空格 類名。類名就是識別符號,命名規則,單詞的首字母大寫,多個單詞的首字母大寫。注意:不是規定,但是最好遵守
- 類名後緊跟一對{}表示類的開始和結束。
-
-
- 汽車有輪胎數 int num;
-
-
- 不需要給num初始化值,因為汽車輪胎數不確定,有4,有6,有8。
-
-
- 有顏色 String color
-
-
- 為什麼使用String 例如定義顏色"紅色"是字串型別。
- 也不需要初始化值。
-
-
- 跑的行為(方法、函式) void run(){}
-
-
- 方法中執行輸出語句。syso("跑啦。。。。");
-
-
public class Car {
String color;// 成員變數 int num; // 成員變數
// 成員函式 void run() { System.out.println(color + "的車,輪胎數:" + num + "個,跑起來了"); } } |
物件的建立
建立Car物件
- 使用new關鍵詞,就像new陣列一樣
- 需要給型的汽車起一個名字,car
- 變數都是有型別的,car屬於什麼型別,屬於Car型別,叫做類型別
- Car car=new Car();
圖紙畫好了,類定義成功了。如何根據圖紙生產汽車,在Java中如何根據類來生產一個物件。
Java中生產汽車比較簡單,通過一個關鍵字”new”, 通過 new Car(); 就在記憶體中產生了一個實體,汽車物件就生產出來了。
汽車物件生產出來後,還沒有名字,為了方便使用,需要起一個名字。就用小寫的C 來表示新車的名字。
Java中的變數都需要有型別。那麼c 是什麼型別呢?c 是Car型別,所以c也叫做類型別變數。
class CarDemo { public static void main(String[] args) { // java 中建立物件,使用new關鍵字。在堆記憶體中開闢了空間。產生了一個實體。 Car c = new Car(); //為了方便使用生產的汽車,就起了一個名字。 //那麼c是什麼型別,是Car型別。叫做類型別變數。 //注意 c是持有的引用,新生產的汽車並沒有直接賦值給c,持有的只是一個引用。c就想電視遙控器一樣。 c.run(); //使用物件的功能。 } }
|
物件成員的呼叫
有了car物件,呼叫物件成員
- 成員變數
- 成員方法
public class CarDemo { public static void main(String[] args) { Car c = new Car(); //物件名.成員變數名將返回成員變數中儲存的數值 int num=c.num; System.out.println(num);
//物件名.成員變數名,也可以給成員變數賦值 c.num = 4; c.color = "black";
//物件名.成員方法(); c.run(); } } |
區域性變數和成員變數
成員變數: 定義在類中變數
區域性變數: 定義在方法中變數
成員變數與區域性變數的區別:
- 應用範圍
-
-
- 成員變數在整個類內都有效
- 區域性變數只在其宣告的方法內有效
-
-
- 生命週期
- 成員變數: 它屬於物件,它隨著物件的建立而建立,隨著物件的消失而消失
- 區域性變數: 使用完馬上釋放空間。
void show(int id){
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
System.out.println(id);
}
}
}
這時候 id,i,j者是在方法內宣告的,全是區域性變數
j當裡層for迴圈執行它的生命週期開始,當裡層for結束,j消失
i當外層for迴圈執行它的生命週期開始,當外層for結束,j消失
id在方法被呼叫時開始,方法結束時,id消失.
- 儲存位置 成員變數屬於物件,它儲存在堆內,堆內的實體,當沒有引用指向其時,才垃圾回收清理 區域性變數存在棧記憶體中,當不在使用時,馬上就會被釋放。
- 初始值
成員變數它儲存在堆中,如果沒有賦初值,它有預設值。
-
-
-
-
-
-
- 整數byte、short、int、long =0;
- char='\uoooo';
- boolean =flase;
- String =null;
- 類型別 =null;
- 陣列 =null;
-
-
-
-
-
區域性變數,如果要想使用必須手動初始化.
-
-
-
-
-
- 方法中,引數列表中,語句中。
- 必須給初始化值,沒有初始值,不能使用
- 在棧記憶體中
-
-
-
-
記憶體分析
案例一:
//汽車
class Car {
//汽車應該具備的屬性
int num;
//汽車具備的顏色
String color;
//汽車跑的行為
public void run(){
System.out.println(num+"輪子的汽車跑起來啦");
}
}
public class CarDemo{
public static void main(String[] args)
{ //建立實體,並且給該實體起一個名字
Car c = new Car();
c.color = "red";
c.num = 4;
c.run();//指揮車進行執行。呼叫格式:物件.物件成員
}
}
案例二分析:
public static void main(String[] args)
{ //建立實體,並且給該實體起一個名字
Car c = new Car();
Car c1 = new Car();
c.color = "red";
c1.num = 4;
System.out.println(c1.color);
c.run();//指揮車進行執行。呼叫格式:物件.物件成員
}
記憶體圖:
案例三
public static void main(String[] args)
{ //建立實體,並且給該實體起一個名字
Car c = new Car();
Car c1 = c;
c.color = "red";
c1.num = 4;
c1.color = "green";
System.out.println(c1.color);
c.run();//指揮車進行執行。呼叫格式:物件.物件成員
}
記憶體圖三
面向物件練習
1:完成修理汽車的功能
2:分析
1:面向物件的思想思考需要什麼物件
1:汽車
1:汽車有輪子
2:有顏色
3:有名字
4:有執行的方法
2:汽車修理廠
1:有名字
2:有地址
3:有修理汽車的方法
3:程式碼實現
1:定義汽車類
2:定義汽車修理廠類
4:測試程式碼
1:建立汽車物件
2:汽車少了輪子無法執行。
3:建立汽車修理廠
1:設定廠名
2:設定地址
3:將汽車拖進修理廠
1:執行汽車修理廠的修車方法,修理汽車
4:取車
1:開走汽車
package oop01;
/* 面向物件之練習 完成修理汽車的功能
汽車類 汽車修理廠類 名字,地址, 修理汽車的功能
*/ public class Demo1 {
public static void main(String[] args) { SCar sc = new SCar(); sc.run(); //將汽車輪子改為3個 sc.num = 3; sc.run();
CarFactory cf = new CarFactory(); cf.name = "幸福修理廠"; cf.addr = "天河區棠東東路預付科貿園a棟206";
cf.repairCar(sc); sc.run();
System.out.println(); } }
class SCar { String name = "smart"; String color = "red"; int num = 4;
void run() { if (num < 4) { System.out.println("汽車壞了,趕緊修理吧。。。。"); } else { System.out.println(name + ":" + color + ":" + num + ":跑起來了。。。。"); }
}
}
class CarFactory { String name; String addr;
void repairCar(SCar sc) { sc.num = 4; System.out.println("汽車修好了。。。。"); } }
|
|
匿名物件
2.1匿名物件:沒有名字的實體,也就是該實體沒有對應的變數名引用。
2.2匿名物件的用途
1,當物件對方法進行一次呼叫的時候,可以使用匿名物件對程式碼進行簡化。
為什麼只對方法,而不呼叫屬性呢?因為匿名物件呼叫屬性沒意義。
如果物件要多成員進行多次呼叫,必須給物件起個名字。不能在使用匿名 物件。
2,匿名物件可以實際引數進行傳遞。
2:匿名物件的簡單演示
1:new Car().run();
3:記憶體結構圖
1:new Car().num=5;
2:new Car().clor="blue";
兩個new 是兩個不同的物件,在堆記憶體中有不同的空間,相互不相互干擾。
4:匿名物件的使用
1:當只使用一次時可以使用匿名物件。執行完畢到;後該物件就變成了垃圾。
new Car().run();
2:執行方法時,可以將匿名物件作為實際引數,傳遞進去。
5:修黑車
1:需求
將小汽車改裝成3個輪子的黑車。
1:汽車類。
2:汽車修理廠
/* 匿名物件 匿名信 修黑車 汽車類 黑車廠類 把汽車的改成黑色3輪車。
*/ class Car { String name = "smart"; String color = "red"; int num = 4;
void run() { System.out.println(name + ":" + color + ":" + num + ":跑起來了。。。。"); }
}
class BlackCarFactory { String name; String addr;
Car repairCar(Car c) { c.num = 3; c.color = "黑色"; System.out.println("改裝成功啦。。。");
} }
class Demo1 {
public static void main(String[] args) {
BlackCarFactory bcf = new BlackCarFactory(); bcf.name = "幸福修理廠"; bcf.addr = "天河區棠東東路御富科貿園a棟206";
// 非匿名物件 Car c = new Car(); c.run(); // 改裝 bcf.repairCar(c); // 取車 c.run();
// 匿名物件一,只使用一次: // 如下建立了2個物件 /* * new Car().run(); * * new Car().run(); */
// 匿名物件二,作為實際引數傳遞 Car c2 = bcf.repairCar(new Car()); c2.run();
System.out.println(); } } |
練習:
- 請問輸出的name屬性是什麼? new Perosn == new Person()相等嗎?
-
總結:
1. 匿名物件設定的屬性永遠無法獲取? 沒有引用變數指向那個物件。
2. 任何兩個匿名物件使用==比較,永遠返回false。
3. 匿名物件主要應用於實參。
- 封裝
-
我們日常使用的電腦主機,把cpu、記憶體、主機板等等都封裝到機箱裡面去。假如沒有機箱的話的出現什麼問題,主機、主機板全部都散落在一處,然後開機沒有開機按鈕,那麼需要我們直接操作接跳線才能把電腦開啟。這樣子的話假如操作不慎的話,會讓機器損壞危險,那麼假如用機箱封裝起來的話,那麼就不需要這樣子做了。體現了封裝的---安全特性。
你拿電腦去加記憶體,可以直接給電腦給維修的人,等他加好記憶體了之後。你拿到的還是那個機箱,裡面發生了怎樣子的變化你並不知道。封裝的第二個好處-將變化隔離。
在機箱裡面提供一個開機按鈕,而不需要你直接使用跳線開機的話,體現了封裝的—便於使用的特性。
只要機箱提供了一個開機的功能,然後無論這個機箱拿到哪裡去,都可以使用這個開機的功能.體現了封裝的---提供重複性的特性。
沒有封裝
模擬問題
- 描述Employee類。定義姓名,工號,性別的成員變數,和工作的方法。成員使用public修飾。
- 建立Employee物件,物件.成員的方式進行賦值。最後該物件呼叫工作方法。
- 總結:如果不使用封裝,很容易賦值錯誤,並且任何人都可以更改,造成資訊的 不安全。
- 問題解決:使用封裝
-
package oop01;
public class EmployeeDemo {
public static void main(String[] args) {
// 建立物件
Employee jack = new Employee();
// 進位制通過類名.成員的形式呼叫成員。初始化例項變數
jack.name = "jack";
jack.id = "123456";
jack.gender = "男";
// 呼叫成員方法
jack.work();
System.out.println();
// 傳入非法的引數
jack.gender = "不是男人";
jack.work();
}
}
class Employee {
String name;
String id;
String gender;
public void work() {
System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
}
}
封裝的實現
1:設定類的屬性為private(關鍵字),不能使用物件名.屬性名的方式直接訪問物件的屬性。
package oop01;
public class EmployeeDemo {
public static void main(String[] args) {
// 建立物件
Employee jack = new Employee();
//編譯報錯
jack.name = "jack";
jack.id = "123456";
jack.gender = "男";
// 編譯報錯
jack.gender = "不是男人";
jack.work();
}
}
class Employee {
//使用了private修飾了成員變數
private String name;
private String id;
private String gender;
public void work() {
System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
}
}
問題:
1:為什麼之前可以通過物件名.屬性名的方式訪問?
2:public 成員修飾符,公共的誰都可以訪問。
3:private 成員修飾符,私有的,只有自己可以訪問。
2:修改Employee類 性別的修飾符修改為private
1:編譯不通過
2:private修飾的成員在自己所在的類中可以使用,在類外邊不可以使用。
3:Employee類的gender的修飾符修改為private後,無法再類外呼叫,那麼如何給gender設定值?
1:對外提供公開的用於設定物件屬性的public方法
1:設定set
2:獲取get
2:在set方法中加入邏輯判斷,過濾掉非法資料。
3:將所有的成員變數封裝加上private,提供get、set方法
package oop01;
public class EmployeeDemo {
public static void main(String[] args) {
// 建立物件
Employee jack = new Employee();
// 呼叫公有方法,給成員變數賦值。
jack.setId("007");
jack.setName("jack");
jack.setGender("男xx");
// 獲取例項變數的值
System.out.println(jack.getGender());
System.out.println(jack.getId());
System.out.println(jack.getName());
// 呼叫成員方法
jack.work();
}
}
class Employee {
private String name;
private String id;
private String gender;
// 提供公有的get set方法
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
public String getId() {
return id;
}
public void setId(String i) {
id = i;
}
public String getGender() {
return gender;
}
public void setGender(String gen) {
if ("男".equals(gen) || "女".equals(gen)) {
gender = gen;
} else {
System.out.println("請輸入\"男\"或者\"女\"");
}
}
public void work() {
System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
}
}
封裝的好處
1:隱藏了類的具體實現
2:操作簡單
3:提高物件資料的安全性
封裝練習
練習:描述一個計算器類
/**
Demo9描述一個計算器類。
*/
// 0. 使用詞霸確定類名
class Calculator
{
// 1. 檢視具體的計算器物件抽取所有計算器具有的共同屬性
public String name = "我的計算器我做主";
public double num1;
public double num2;
public char option;
// 2. 檢視具體的計算器物件抽取所有計算器具有的共同功能
// 2.1 定義接受資料的功能函式
public void init( double a , char op , double b ){
num1 = a;
option = op;
num2 = b;
}
// 2.2 定義計算的功能
public void calculate(){
switch ( option )
{
case '+': System.out.println( name + " : " + num1 + " + " + num2 + " = " + ( num1 + num2 ) );
break;
case '-': System.out.println( name + " : " + num1 + " - " + num2 + " = " + ( num1 - num2 ) );
break;
case '*': System.out.println( name + " : " + num1 + " * " + num2 + " = " + ( num1 * num2 ) );
break;
case '/': {
if( num2 != 0 )
System.out.println( name + " : " + num1 + " / " + num2 + " = " + ( num1 / num2 ) );
else
System.out.println("除數不能為0!");
break;
}
case '%': {
// 1.處理結果的符號問題,使得結果的符號滿足數學的要求
// 2.解決NaN的問題
System.out.println( name + " : " + num1 + " % " + num2 + " = " + ( num1 % num2 ) );
break;
}
default : System.out.println("你在搗亂,我不理你,氣死你......");
}
}
}
class Demo9
{
public static void main(String[] args)
{
Calculator cal = new Calculator();
cal.init( 41 , '%' , 0 );
cal.calculate();
System.out.println("計算完畢!再來一次......");
}
}
- 構造方法1.我們人出生的時候,有些人一出生之後再起名字的,但是有些人一旦出生就已經起好名字的。那麼我們在java裡面怎麼在物件一旦建立就賦值呢?
構造方法的作用
構造方法作用:對物件進行初始化.
建構函式與普通的函式的區別
- 一般函式是用於定義物件應該具備的功能。而建構函式定義的是,物件在呼叫功能之前,在建立時,應該具備的一些內容。也就是物件的初始化內容。
- 建構函式是在物件建立時由jvm呼叫, 給物件初始化。一般函式是物件建立後,當物件呼叫該功能時才會執行。
- 普通函式可以使用物件多次呼叫,建構函式就在建立物件時呼叫。
- 建構函式的函式名要與類名一樣,而普通的函式只要符合識別符號的命名規則即可。