Java小白入門教程(9)——面向對象

提綱:

<code>1、面向對象 2、類和對象 3、方法的重載 4、構造方法 5、this關鍵字 6、匿名對象 7、作業/<code>


一、面向對象

1.1、生活中什麼是面向對象

<code>洗衣服,吃飯 面向過程:關注點是過程 ————站在一個執行者的角度去考慮事情,做事情 //step1.找個盆 //step2.收集要洗的衣服 //step3.放水,放洗衣粉。。 //step4:洗一洗 //step5:曬一曬 面向對象:關注點是對象 ————站在指揮者的角度 //step1:找個對象 //step2:讓他洗衣服 生活中的面向對象:找合適的人,做合適的事兒。。 生活中的面向過程:親力親為,按照流程步驟來,一步一步,吭哧吭哧。。。 ​ 代碼中: Arrays類 sort();-->排序 binarySearch();-->搜索 Scanner類 sc.nextInt(); sc.next(); sc.nextDouble();/<code>



1.2、面向對象和麵向過程

<code>面向對象:(OOP) 不是一種語言,而是一種編程思想。 面向對象程序設計:(Object Oriented Programming) Object:對象 Oriented:方向,定向 Programming:程序 面向過程: 關注點在過程上(步驟) step1,step2,step3.。。。。 總和分析,按照步驟實現即可。 ​ 面向對象: 關注點在對象上 萬事萬物皆對象。 A:分析當前的問題域中所涉及的對象。 B:這些對象有什麼樣的特徵和功能。 外部特徵:靜態屬性 動作行為:動態屬性 C:對象和對象之間的關係。 繼承關係,聚合關係,關聯關係。。。 類的堆砌。/<code>


二、類和對象

2.1、類和對象

<code> 類:其實指的就是類別。對同一類事物的統稱。對這類事物進行描述,--->創建class 就是一個抽象的概念。 對象: 類中的一個具體的實例,客觀存在的,能用。個體。 /<code>

如何定義一個類?

要有能夠描述這一類別的外部特徵——我們叫做屬性(靜態屬性)
變量就可以。(名詞)要有能夠描述這一類別的行為功能——我們叫做方法(動態屬性)
方法就可以。(動詞)

2.2、Java中定義類的格式

<code>/* class ClassName{//類名首字母大寫 //屬性描述:外部特徵 //行為描述:能夠幹啥 } */ 要求: 1、CLassName要求符合駝峰命名法,首字母大寫,見名知意。 2、屬性描述:外部特徵,用於描述這個類別的一些特徵,而這些特徵通過一個"詞"來描述清楚,比如姓名,年齡。使用變量來表示。——【成員變量】Field,詞義"字段" 3、行為描述:能夠幹啥,用於描述這個類別的一些行為功能,而這些行為功能,是一個動作行為,比如吃飯,睡覺。使用方法來表示。——【成員方法】Method,詞義"方法" 不要加static。/<code>

方法:就是一段具有獨立功能的代碼。

2.2.1 step1聲明類

<code>public class Person{//類的名字 ​ }/<code>


2.2.2 step2聲明類中的【成員變量】

<code>public class Person { //step2:成員變量 String name;//使用String類型的變量name,表示人類中的姓名 int age;//使用int類型的變量age,表示人類中的年齡 char sex;//使用char類型的變量sex,表示人類中的性別 }/<code>


2.2.3 step3聲明類中的【成員方法】

<code>public class Person { //step2:成員變量 String name;//使用String類型的變量name,表示人類中的姓名 int age;//使用int類型的變量age,表示人類中的年齡 char sex;//使用char類型的變量sex,表示人類中的性別 //step3:成員方法 public void eat(){ System.out.println("吃飯啦。。"); } public void sleep(){ System.out.println("睡覺啦。。"); } public void daDouDou(){ System.out.println("打豆豆。。。"); } } ​/<code>

2.3、類的對象

2.3.1 創建類的對象

創建對象,也叫做類的實例化。對象,也叫類的實例。

<code>/* new關鍵字 new,詞義:新的,新建 new 關鍵字,專門用於新建對象。 */ Scanner sc = new Scanner();//Scanner也是個類,Person也是個類。 int[] arr = new int[5]; ​ 語法結構: /* 類名 對象名 = new 類名(); */ Person p1 = new Person();/<code>

step2:根據類,實例化對象

step1:創建類


2.3.2通過對象訪問屬性

<code>/* int[] arr = new int[5]; 獲取數組的長度: arr.length arr的長度 */ 對象訪問屬性的語法:就是一個. //給對象的屬性,進行賦值 p1.name = "王二狗";//給p1這個對象的name屬性進行賦值 p1.age = 18; p1.sex = '男'; ​ ​ //獲取對象的屬性值 System.out.println("姓名:"+p1.name); System.out.println("年齡:"+p1.age); System.out.println("性別:"+p1.sex);/<code>


2.3.3通過對象訪問方法

<code>/* Scanner sc = new Scanner(); sc.nextInt(); */ Scanner,就是一個class,一個類 sc,是根據Scanner創建出來的一個對象 ​ 對象調用類中的方法,語法,也是. 對象.方法名(); p1.eat(); p1.sleep(); p1.daDouDou();/<code>


2.3 內存分析

實例代碼:

<code>package com.qf.demo01; ​ public class Test1Person { ​ public static void main(String[] args) { //step1:創建Person類的對象 //語法:類名 對象名 = new 類名(); Person p1 = new Person(); System.out.println(p1);//打印p1的值,p1是引用類型,打印都是p1指向的對象的地址。 System.out.println(p1.name); System.out.println(p1.age); System.out.println(p1.sex); /* * com.qf.demo01.Person@15db9742 * 包名.類名@編碼值 ---->理解為p1的內存地址。 * * java中的數據類型: * 基本類型:byte,short,char,int,long,bolean,float,double * 引用類型: * 數組,類類類型 * */ //step2:通過對象訪問屬性,語法是. //給對象的屬性,進行賦值 p1.name = "王二狗";//給p1這個對象的name屬性進行賦值 p1.age = 18; p1.sex = '男'; //獲取對象的屬性值 System.out.println("姓名:"+p1.name); System.out.println("年齡:"+p1.age); System.out.println("性別:"+p1.sex); //step3:通過對象,訪問成員方法--->理解為就是對象調用成員方法 p1.eat(); p1.sleep(); p1.daDouDou(); } ​ } ​/<code>

內存分析圖


示例代碼:

<code>package com.qf.demo01; ​ public class Test2Person { ​ public static void main(String[] args) { //1.創建一個Person類的對象 Person p1 = new Person(); System.out.println(p1);//p1的內存地址:com.qf.demo01.Person@15db9742 p1.name = "張三狗"; p1.age = 19; p1.sex = '男'; System.out.println(p1.name);//張三狗 System.out.println(p1.age);//19 System.out.println(p1.sex);//男 //2.再創建一個Person類的對象 Person p2 = new Person(); System.out.println(p2);//p2的內存地址,com.qf.demo01.Person@6d06d69c p2.name = "李小花"; p2.age = 17; p2.sex = '女'; System.out.println(p2.name);//李小花 System.out.println(p2.age);//17 System.out.println(p2.sex);//女 //3. Person p3 = null;//僅僅聲明瞭Person類型的對象p3,但是實際上,並沒有在堆內存中,創建出真正的對象。 /* * NullPointerException,空指針異常 * * 對象不存在,就是個null, * 強行的訪問對象的屬性或調用方法,就會空指針異常。 */ //System.out.println("---->"+p3.name);//報錯啦:NullPointerException p3 = p1;//將p1的值(p1對象的內存地址),賦值給p3,結果-->p1和p3存儲的是同一個對象的內存地址。 p3.name = "李鐵柱"; System.out.println(p1.name);//李鐵柱 System.out.println(p2.name);//李小花 System.out.println(p3.name);//李鐵柱 Person p4 = new Person(); System.out.println(p4);//? p4.name = "王二丫"; p4.age = 18; p4.sex = '女'; System.out.println(p4.name ); System.out.println(p4.age); System.out.println(p4.sex); p4 = p1;//改變對象的內存地址了,就不再指向原來的內存對象。 System.out.println(p1.name); System.out.println(p3.name); System.out.println(p4.name); } ​ } ​/<code>

內存分析圖:


2.5、方法的重載:overload

<code>概念:一個類中的,一個功能方法的多種體現形式(有不同的方法體)。 舉例: 1、人類,有吃的功能:eat() eat(食物); eat(藥); eat(口香糖); 2、求和的功能: getSum(int i,int j); getSum(double d1, double d2); 3、水: 常溫:液態 0度以下:固態 100度以上:氣態 就是同一個功能的方法,因為參數的不同,調用的具體的方法也不同。 如何判定多個方法是否是重載的?衡量標準,要同時滿足以下三條: A:必須同一個類中。 B:方法名稱必須一致。 C:參數列表必須不同。(順序,個數,類型) 和static,public,返回值,void等等都沒有關係。 優點: 1、簡化了開發的壓力 2、簡化了記憶的壓力 3、調用方法更方便,更簡潔,又滿足了不同的情況 基本原理: 當方法名稱一致時,通過形式參數列表的不同來選擇要執行的方法。/<code>

示例代碼:

<code>package com.qf.demo01.overload; ​ import java.util.Arrays; ​ /* * 方法的重載: * 同一個功能: * 根據參數的不同,執行的具體的方法也不同 * * 衡量方法是否重載: * 1、同一個類中 * 2、方法名必須一致 * 3、參數列表必須不同:類型,個數,順序 */ public class Test1 { //求兩個數的和: //求兩個整數的和 public static void getSum(int i,int j){ int sum = i + j; System.out.println(i+" + " + j +"的總和是:"+sum); } public static void getSum(double d1, double d2){ double sum = d1 + d2; System.out.println("總和是:"+sum); } public static void getSum(int i,double j){ } public static void getSum(double d1,int i1){ } ​ public static void main(String[] args) { getSum(1, 2); getSum(3.14, 4.21); ​ } } ​/<code>



2.6、構造方法

構造方法:是一個很特殊的方法。

聲明的語法:public 類名(){}修飾符:只能有訪問權限的修飾符,public。不能加static。返回值:沒有返回值,也不能寫void。方法名:必須和類名相同


調用的方式:new 關鍵字調用new關鍵字後面跟著構造方法即可。


作用:專門用於創建對象。

普通方法:一段具有特殊功能的代碼。而且可以被多次調用執行。

聲明的語法:public static void main(String[] args){}調用的方式:方法名(實參);作用:1、避免重複的代碼增強程序的可讀性。2、提高程序的可維護性。


<code>1、編寫java的源代碼(給人看):XXX.java 2、將源文件進行編譯(機器執行的就是這個字節碼文件):XXX.class javac命令 javac XXX.java 3、JVM執行字節碼文件:XXX.class java命令 java XXX ​ Java反編譯工具:我們現在將class文件,進行反編譯,可以看見類似於底層語言 javap -c -l -private XXX.class /<code>

2.6.1 Java編譯器提供的默認的構造方法

<code>問題:創建對象的時候,代碼:new Person();調用的這個Person()這個方法,在程序中並沒有寫,哪來的? ​ 試著將Person.class文件進行反編譯:/<code>


結論:通過反編譯工具,發現了一些和源代碼不相符的內容,這就是javac編譯器,自動給代碼中添加的構造方法。用於創建對象。

java編譯器,發現代碼中沒有任何的構造方法,在編譯時,會自動的幫我們添加一個無參的構造方法。

如果代碼中自己寫了構造方法,那麼編譯器不再幫我們添加無參的構造方法。



2.6.2 自定義的構造方法

<code>記住一條:如果一個類中,沒有寫任何的構造方法,那麼編譯器自動添加一個無參的構造方法。但是如果你寫了構造方法,那麼編譯器不再添加了。 我們寫程序的規則: 無參構造要寫 有參構造看實際情況 一個類中可以有多個構造方法的。也是方法的重載。 創建對象的語法: new 構造方法(可能有參數); 如果添加自己定義的構造方法: 語法規則: public 類名(){ ​ } public 類名(參數列表){ 將參數的數值,賦值給屬性即可。 }/<code>

如何創建一個對象?就是通過new這個關鍵字,調用一個類的構造方法。就創建了對象。

先聲明,再調用--->普通方法,還適合構造方法。

如果一個類中,沒有手動的寫一個構造方法的話,那麼編譯器會自動的添加一個無參的構造方法。

示例代碼:

<code>class Person{ String name; int age; public Person(){//無參的構造方法 } public Person(String n,int a){//有參的構造方法 name = n; age = a; } } class Test{ public static void main(String[] args){ Person p1 = new Person(); p1.name = "李小花"; p1.age = 18; Person p2 = new Person("王二狗",18); } }/<code>


注意點:

1、如果代碼中,沒有寫構造方法。編譯器會自動的添加一個無參的構造方法。


2、如果代碼中,寫了構造方法。編譯器都不會再給我們添加無參的構造方法。編碼習慣:寫了有參構造,再寫上無參構造。


對比一下構造方法和普通方法:

2.7、this關鍵字

詞義:這個。

2.7.1 就近原則問題

<code>當寫代碼的時候,要給成員變量,參數,局部變量等等,要進行命名。根據見名知意的原則,很容易就命名衝突了。 在程序當中,有個就近原則,一旦名字衝突,就要看離哪個聲明近。 導致名稱中成員變量和局部變量的命名衝突!!! public Person(String name,int age){//name="李小花" name = name; //=兩側的name,都是指參數 age = age; } 因為命名規範,見名知意,成員變量和局部變量,命名相同了。 因為就近原則問題:構造方法Person中,name和age,都會看成了這個參數,就是局部變量。 希望有一種方式,來告訴編譯器:=左邊的是成員變量,=右邊的才是參數。 可以藉助於this這個關鍵字解決。/<code>

2.7.2 this的用法一

表示當前對象。

<code>this.屬性,沒有this的就是局部變量。可以解決命名衝突的問題。 public Person(String name,int age){//name="李小花" this.name = name; //=左側的是this的name屬性 this.age = age; } 使用this關鍵字,明確的告訴編譯器,this後的這個name,就是成員變量。對象的屬性。沒有this的就是參數。 解決成員變量和局部變量的命名衝突。 this點的就是成員變量,沒有this的就是局部變量。/<code>

示例代碼:

<code>package com.qf.demo03; ​ public class Person { //成員變量 String name;//屬性,成員變量,人有姓名 int age; public Person(){ } /* * 就近原則:成員變量和局部變量命名衝突了。方法中name默認都是參數。 */ public Person(String name,int age){//name="李小花" this.name = name; this.age = age; } public void eat(){ System.out.println(name+",吃東西啦。。"); } //this,當前的對象。誰調用誰就是當前的對象 //當p1調用的時候,this就指代p1 //當p2調用的時候,shis就指代p2 //在類中提供一個功能:成員方法 public void showInfo(){ System.out.println("姓名:"+this.name+",年齡:"+age); } } ​/<code>

2.7.3 this的用法二

this()指代當前類的構造方法。

<code>this(參數),就表示的構造方法。 如果一個類中,有多個構造方法,之間存在了調用關係,那麼使用this()來指代這個構造方法。具體指代哪個構造方法,要靠參數來區分。 注意點:當this()指代構造方法,那麼必須放在首行。/<code>

示例代碼:

<code>package com.qf.demo03; ​ public class Student { String name; int age; String sex; double score; public Student(){ System.out.println("無參的構造方法,Student()..."); } public Student(String name,int age){//給name和age屬性賦值 System.out.println("有參構造方法。。2個參數。。"); this.name = name; this.age = age ; } public Student(String name,int age,String sex,double score){ this(name,age);//this(),指代構造方法。 System.out.println("有參構造方法。。4個參數。。"); // this.name = name; // this.age = age; this.sex = sex; this.score = score; } public void showInfo(){ System.out.println("姓名:"+name+",年齡:"+age+",性別:"+sex+",成績:"+score); } } ​/<code>

2.8、匿名對象

<code>創建對象的語法: Person p1 = new Person(); //=左側在做對象的聲明,開闢的是棧內存 //=右側,才是真正的創建對象 //結果:內存中,創建了一個對象,對象的地址,賦值給p1。 匿名對象,就是隻有=右側,沒有=左側。 new 構造方法(必要的參數); 匿名對象的用途: 1、使用匿名對象,直接調用類的方法。 2、匿名對象直接作為一個方法的參數。 注意點: 匿名對象只能使用一次。隨著它的創建而使用一次。(一次性的) 優勢: 1、使用後即銷燬,就是被GC回收。 2、代碼書寫方法,提高效率。/<code>

示例代碼:

<code>package com.qf.demo01; ​ public class Test1 { ​ public static void main(String[] args) { //創建正常的對象,有引用,有對象 Person p1 = new Person(); //通過p1,來指揮對象:可以訪問屬性,賦值,取值,,可以調用方法 p1.name = "王二狗"; p1.age = 19; System.out.println(p1.name); System.out.println(p1.age); p1.eat(); p1.eat(); //創建一個匿名對象,沒有棧的引用,只有堆中的對象。 //侷限:只能使用一次,創建的時候使用一次。 new Person().eat(); new Person("李小花",18).eat(); //只有=左側 Person p2 = null;//只有對象聲明 p2.eat(); } ​ } ​/<code>



三、作業


<code>1.this關鍵字的用法寫3遍,記下來. 2.創建一個Teacher類。設置屬性和方法。無參構造方法和有參構造方法。並創建對象,打印對象的屬性信息。執行成員方法。 ​ 3.創建一個Computer類,設置該類的屬性,以及一個方法,用於顯示計算機的屬性信息.並添加構造方法,無參的和有參的.分別創建該類的對象.執行方法. ​ 4.創建一個Girl類,設置屬性name,age,無參構造和有參構造.創建該類對象,為屬性賦值.打印屬性值. 5.(選做)設計一個學生類,有姓名,有年齡,有性別,有英語成績,數學成績,語文成績,提供無參構造和有參構造 ​ 設計方法,求總分,平均分,以及打印學生的信息。3個對象。/<code>