Java筆記--03

面向過程與面向對象的區別?(蓋飯、蛋炒飯)
採用面向過程必須瞭解整個過程,每個步驟都有因果關係,每個因果關係都構成了一個步驟,多個步驟就構成了一個系統,因爲存在因果關係每個步驟很難分離,非常緊密,當任何一個步驟出現問題,將會影響到所有的系統。高耦合:代碼和代碼之間的聯繫程度高。
面向對象會將現實世界分割成不同的單元(對象),實現各個對象,如果完成某個功能,只需要將各個對象協作起來就可以。
面向對象的三大特徵
封裝
繼承
多態
類和對象的概念
類是對具有共性事物的抽象描述,是在概念上的一個定義
通常根據名詞(概念)來發現類,如在成績管理系統中,學生、班級、課程、成績
學生-張三
班級-315
課程-軟件工程
成績-張三成績
以上”張三”,”315”,”軟件工程”,”張三成績”他們是具體存在的,稱爲對象,也叫實例
也就是說一個類的具體化,就是對象或實例。
爲什麼面向對象成爲主流技術?
主要是因爲面向對象更符合人的思維模式,更容易分析現實世界
從軟件的開發生命週期來看,基於面向對象可以分爲三個階段
OOA(面向對象的分析)
OOD(面向對象的設計)
OOP(面向對象的編程)–Java就是一個純面向對象的語言
類=屬性+方法
類是一種引用數據類型
屬性來自於類的狀態,而方法來自於類的動作
類的定義
類的修飾符 class 類名 extends 父類名 interface 接口名{ 類體:屬性和方法組成}
定義在類體中的變量分爲兩種:
如果沒有static修飾就是成員變量也叫實例變量或非靜態變量,該變量是對象級別的,必須先有對象才能訪問,不能使用類直接訪問,成員變量在堆中的對象中存儲,成員變量如果沒有手動賦值,系統則默認賦值
系統默認
基本數據類型:
byte、short、int、long 0
float、double 0.0
char \u0000
boolean false
引用數據類型 null
成員變量只屬於當前的對象(只屬於對象,不屬於類),只有通過對象纔可以訪問成員變量(訪問方式”引用.成員變量”),通過類不能直接訪問成員變量
如果有static修飾就是類變量或靜態變量,該變量可以使用類直接訪問
Java中所有new出來的數據統一被存儲在堆區中,程序員無法對堆區數據直接操作,只能通過內存地址間接操作。
定義在方法中的變量是局部變量(包括方法參數列表)
局部變量在棧中存儲
Student stu1=new Student();
stu1是一個局部變量(不是對象),這個變量是Student類型,也就是一個引用類型,stu1稱作”引用
stu1該局部變量稱作引用,引用中保存的是對象在堆中的內存地址,通過”引用”去間接訪問堆中的對象
面向對象的封裝性
1.屬性私有化
2.對外提供公開的set和get方法
關於Java的構造函數
1.構造方法語法:
[修飾符列表] 構造方法名(形式參數列表){
方法體;
}
2.構造方法的方法名必須和類名一致
3.構造方法的作用是什麼?
第一、創建對象
第二、給成員變量賦值(也就是初始化成員變量)
4.構造方法應該如何調用?
new 構造方法名(實參);在堆中開闢空間存儲對象
5.如果一個類沒有提供任何構造方法,系統默認提供無參數構造方法
如果一個類已經手動的提供了構造方法,那麼系統不會再提供任何構造方法。
6.成員變量到底什麼時候賦值?
只有在調用構造方法的時候,纔會給成員變量賦值
構造方法主要用來創建類的實例化對象,可以完成創建實例化對象的初始化工作,
聲明格式: 構造方法修飾詞列表 類名(方法參數列表)
構造方法修飾詞列表:public、proteced、private
類的構造方法和普通方法一樣可以進行重載
構造方法具有的特點:
1. 構造方法名稱必須與類名一致
2. 構造方法不具有任何返回值類型,即沒有返回值,關鍵字 void 也不能加入,
加入後就不是構造方法了,就成了普通的方法了
3. 任何類都有構造方法,如果沒有顯示的定義,則系統會爲該類定義一個默認的構造器,
這個構造器不含任何參數,如果顯示的定義了構造器,系統就不會創建默認的 、不含參數的構造器了。


Java內存劃分
Java虛擬機管理的內存分爲三大塊
棧區、堆區和方法區
其中,
方法區:用來存儲類的所有信息,包括所有的方法,靜態變量,常量
棧區:每調用一個方法,會創建一個棧幀,存放局部變量
堆區:存放new出來的對象,此對象由垃圾收集器收集,垃圾收集器針對的就是堆區

什麼時候垃圾回收器會回收垃圾?
如果堆中的對象沒有更多的引用指向它,則該對象變成了垃圾,等待垃圾回收器的回收。
當不使用new關鍵字時,出現的問題?
Student s=new Student();
s=null;//賦值覆蓋new Student();使局部變量s不指向任何對象
System.out.println(s.name);//編譯不報錯,運行報空指針異常
參數傳遞
只要是基本類型,傳遞過去的都是值
除了基本類型外都是址傳遞
this關鍵字
1.this是什麼?
this是一個引用類型,在堆中的每一個java對象上都有this,this保存內存地址指向自身
2.this能用在哪些地方?
第一、this可以用在成員方法中
this用在成員方法中,誰去調用這個成員方法,this就代表誰,this指的就是當前對象。
第二、this可以用在構造方法中
語法:this(實參);//用來在構造方法中調用另一個構造方法且這個語句只能放在構造方法中的第一句
目的:代碼重用
this不能用在靜態方法中
靜態方法的執行根本不需要java對象的存在,直接使用類名. 的方式調用
而this代表的是當前對象,所以靜態方法中根本沒有this
this可以用來區分成員變量和局部變量
static關鍵詞
1.static修飾的變量叫做”靜態變量”
2.static修飾的方法叫做”靜態方法”
3.static還可以定義靜態語句塊
靜態語句塊和實例語句塊
static修飾的語句塊叫靜態語句塊,靜態語句塊在類加載階段執行,且只執行一次,並且是自上而下的順序執行
沒有static修飾的語句塊叫實例語句塊,每一次調用構造方法之前會執行一次,實例語句塊執行順序也是自上而下。
靜態方法
一般情況下工具類中的方法大部分都是靜態方法
靜態方法不創建對象也能直接訪問該方法
可以使用”類名.”方式調用
靜態方法中不能直接訪問非靜態數據
靜態方法中不能使用this
靜態方法按照正規的方式訪問:”類名.”
靜態方法也能用”引用.” 方式訪問,實質:編譯階段檢查出引用是static類型,編譯通過,
運行的時候,仍然使用”類名.”的方式訪問
StaticTest s=null;//StaticTest是類名
s.m1();//m1方法是靜態方法,這樣的話運行也不報空指針異常//靜態方法執行不需要對象,即使用引用底層用的也是”類名.”
變量詳解
變量分類;
1.局部變量 在棧中存儲
2.成員變量(實例變量、非靜態變量) 在堆中的對象中存儲,在創建對象的時候初始化
3.靜態變量 在方法區中存儲,所有java對象共享這一份,所以靜態變量是類級別的,使用”類名.”方式訪問,在類加載階段賦值,並且只賦值一次
什麼時候聲明成靜態變量?
如果這個屬性所有的對象都有,並且這個屬性的值是相同的,則該屬性聲明成靜態的。
關於代碼的順序
public class Test{
//編譯通過
static int i=10;
static {
System.out.println(i);
}
}
public class Test{
//報非法向前引用異常
static {
System.out.println(i);
}
static int i=10;
}
類中都可以有什麼?
類{
//可以通過”類名.”訪問,也可以通過”引用.”訪問,底層也是”類名.”方式訪問
//1.靜態變量
//2.靜態方法

    //必須對象存在纔可以訪問,採用"引用."
    //3.成員變量
    //4.成員方法

    //創建對象,給成員變量賦值
    //5.構造方法

    //類加載時執行且只執行一次
    //6.靜態語句塊

    //構造方法每次調用之前執行
    //7.實例語句塊

    //用在成員方法和構造方法中
    //8.this

  }

空指針異常:空引用訪問成員拋空指針異常,空引用訪問靜態不拋異常
java類的繼承
繼承的基本作用:代碼的重用
繼承最重要的作用:方法可以重寫
java語言中子類繼承父類,會將父類中所有的數據全部繼承,包括私有的也能繼承過來,
但是在子類中無法直接訪問父類中的私有的數據,但是可以間接訪問
注意:構造方法無法被子類繼承
關於方法覆蓋
什麼時候要進行重寫?
如果父類中的方法已經無法滿足當前子類的業務需求,需要將父類中的方法進行重寫一遍
2.子類如果重寫父類中的方法,則子類對象調用的一定是重寫之後的方法
3.發生方法覆蓋的條件?
第一、發生在具有繼承關係的兩個類之間
第二、必須具有相同的方法名,相同的返回值類型,相同的參數列表
第三、重寫的方法不能比被重寫的方法擁有更低的訪問權限
第四、重寫的方法不能比被重寫的方法拋出更寬泛的異常
第五、私有的方法不能被覆蓋
第六、構造方法無法被覆蓋,因爲構造方法無法被繼承
第七、靜態的方法不存在覆蓋,因爲靜態方法執行和對象無關
第八、覆蓋指的是成員方法,和成員變量無關
關於java語言中向上轉型和向下轉型
1.向上轉型(upcasting):子–>父
2.向下轉型(downcasting):父–>子
注意:無論是向上轉型還是向下轉型,兩個類之間必須要有繼承關係
向上轉型又被稱作:強制類型轉換
父類型的引用指向子類型對象
程序分兩個階段:編譯階段,運行階段
Animal a1 = new Cat();//Cat繼承了Animal類
程序在編譯階段只知道a1是一個Animal類型,程序在運行的時候堆中的實際對象是Cat類型
a1.eat();//Animal和Cat中都有eat();方法
程序在編譯階段a1被編譯器看做Animal類型
所以程序在編譯階段a1引用綁定的是Animal類中的eat方法(靜態綁定)
程序在運行的時候堆中的對象實際是Cat類型,而Cat已經重寫了eat方法
所以程序在運行階段對象的綁定的方法是Cat中的eat方法(動態綁定)
向下轉型:強制類型轉換
Animal a1=new Cat();//向上轉型又被稱作:強制類型轉換
要執行Cat類中的move方法,而該方法在Animal類中沒有,該怎麼做?
只能強制類型轉換,需要加強制類型轉換符
Cat c1=(Cat)a1;
判斷以下程序運行的時候會出現什麼問題?
Animal a2 = new Dog();//Dog繼承了Animal
Cat c2 = (Cat)a2;//java.lang.ClassCastException
在做強制類型轉換的時候程序是存在風險的!!
爲了避免java.lang.ClassCastException的發生,java引入了instanceof運算符
用法:
1.instanceof運算符的運算結果是boolean類型
2.(引用 instanceof 類型)–>true/false
例如:(a instanceof Cat)如果結果是true,表示a引用指向堆中的java對象是Cat類型
推薦:在做向下轉型的時候要使用instanceof運算符判斷,避免ClassCastException
多態的好處?
1.使用多態可以使代碼之間的耦合度降低
2.項目的擴展能力強
推薦:編程的時候不要面向具體編程,要面向父類型編程,面向抽象編程
super關鍵字
1.super不是引用類型,super中存儲的不是內存地址,super指向的不是父類對象
2.super代表的是當前子類對象中的父類型特徵
3.什麼時候使用super?
子類和父類都有某個數據,例如,子類和父類中都有name這個屬性
如果要在子類中訪問父類中的name屬性,需要使用 super.
4.super可以用在什麼什麼地方?
第一、super可以用在成員方法中,不能用在靜態方法中
第二、super可以用在構造方法中
super關鍵字用在構造方法中
語法:super(實參);
作用:通過子類的構造方法去調用父類的構造方法
語法規則:一個構造方法第一行如果沒有this(…);也沒有顯示的去調用super(…);
系統會默認調用super();
注意:super(…)的調用只能放在構造方法的第一行
super(…)和this(…)不能共存
super(…);調用了父類的構造方法,但是並不會創建父類對象
通過子類的構造方法去調用父類的構造方法,作用是:給當前子類對象中的父類型特徵賦值
在java語言中只要是創建java對象,那麼Object中的無參構造方法一定會執行

注意:單例模式的類型沒有子類,無法被繼承,因爲子類繼承父類會默認調用父類中的無參構造方法並且單例模式中的構造方法私有化了,不能被子類調用
finfal關鍵字
1.final修飾的類無法被繼承
2.final修飾的方法無法被覆蓋
3.final修飾的局部變量,一旦賦值,不可改變
4.final修飾的成員變量必須顯示的初始化即必須手動初始化
final修飾的成員變量一般和static連用
常量:值不可再改變的變量
java規範中要求所有的常量變量名要大寫
5.final修飾的引用類型,該引用類型不可再重新指向其他的java對象
6.final不能修飾抽象類,也不能修飾抽象方法,因爲抽象類要被繼承,抽象方法要被重寫
抽象類
1.如何定義抽象類?
class關鍵字前加abstract
2.抽象類無法被實例化
3.雖然抽象類無法實例化,但是抽象類也有構造方法,該構造方法是給子類創建對象用的
4.抽象類中可以定義抽象方法
抽象方法的語法:在方法的修飾符列表中添加abstract關鍵字,且抽象方法應該以”;”結束,不能帶有”{}”
例如:public abstract void m1();
5.抽象類中不一定有抽象方法,但抽象方法必須出現在抽象類中
6.一個非抽象的類繼承抽象類,必須將抽象類中的抽象方法覆蓋,實現,重寫
接口
接口也是一種引用類型,可以等同看做類
1.如何定義接口,語法:
[修飾符] interface 接口名{}
2.接口中只能出現:常量、抽象方法
3.接口其實就是一個特殊的抽象類,特殊在接口是完全抽象的
4.接口中沒有構造方法,無法被實例化
5.接口和接口之間可以多繼承
6.一個類可以實現多個接口(這裏的”實現”可以等同看做”繼承”)
7.一個非抽象的類實現接口,需要將接口中所有的方法”實現/重寫/覆蓋”
public interface A{
//常量必須用public static final修飾
public static final double PI=3.14;
//public static final是可以省略的
byte MAX_VALUE=127;
//接口中所有的抽象方法都是public abstract
public abstract void m1();
//public abstract是可以省略的
void m2();
}
8.實現接口用implements關鍵字,implements和extends意義相同
如果要實現多個接口,在接口之間加”,”
例如:class D implements A,B,C{重寫接口A,B,C中的方法}
9.接口和抽象類都能完成某個功能,優先選擇接口
因爲接口可以多實現,多繼承,並且一個類除了實現接口之外,還可以去繼承其他類(保留了類的繼承)
接口的作用:
1.可以使項目分層,所有層都面向接口開發開發效率提高了
2.接口使代碼和代碼之間的耦合度降低,就像內存條和主板的關係,變得”可插拔”,可以隨意切換
關於Object中的toString方法
SUN在Object類中設計toString方法的目的:返回java對象的字符串表示形式
在顯示的開發過程中,Object裏邊的toSting方法已經不夠用了
因爲Object的toString方法的實現結果不滿意
Object中的toString方法就是要被重寫的
SUN是這樣實現toString方法的
public String toString(){
return getClass().getName()+”@”+Integer.toHexString(hasCode);
}
Object中的toString方法返回:類名@Java對象的內存地址經過哈希算法得出的int類型再轉換成十六進制
這個輸出結果可以等同看做java對象在堆中的內存地址
print和println方法後面的括號中如果是一個引用類型,會默認調用引用類型的toString方法
關於Object中的equals方法
java對象中的equals方法的設計目的:判斷兩個對象是否一樣
Object中的equals方法比較的是兩個引用的內存地址
在現實的業務邏輯中,不應當比較內存地址,應該比較內容
所以Object中的equals方法也要重寫,要根據需求規定重寫equals方法
==兩邊如果是引用類型,則比較的內存地址,地址相同爲true,否則false
關於java語言中如何比較兩個字符串是否一致
在java中比較兩個字符串是否一致,不能用”==”
只能調用String類的equals方法(String已經重寫了Object中的equals方法,比較的是內容)
關於Object中的finalize方法
finalize方法什麼時候調用?
1.finalize方法每個java對象都有
2.finalize方法不需要程序員去調用,由系統自動調用
3.java對象如果沒有更多的引用指向它,則該Java對象成爲垃圾數據,
等待垃圾回收器的回收,垃圾回收器在回收這個java對象之前會自動調用該對象的finalize方法
finalize方法是該對象馬上就要被回收了,例如,需要釋放資源,則可以在該方法中釋放
程序員只能”建議”垃圾回收器回收垃圾
System.gc();
要想執行finalize方法有效果,就要重寫finalize方法
而且就算執行finalize方法也不一定回收垃圾,
因爲可以在finalize方法中挽救該對象,即把該引用重新賦值給該對象
關於Object中的hasCode方法
hasCode方法返回的是該對象的哈希碼值
java對象的內存地址經過哈希算法得出的int類型的數值
關於package和import
包機制:
1.爲了解決類的命名衝突問題,在類名前加命名空間(包機制)
2.在java中使用package語句定義包
3.package語句只能出現在.java源文件的第一行
4.package定義的格式,通常採用公司域名倒敘方式
package定義的全格式:公司域名倒敘.項目名.模塊名;
5.完整的類名是帶有包名的
6.帶有package語句的java源文件必須這樣編譯:
javac -d 生成路徑 java源文件路徑
7.運行:
java 全類名 //帶包名
import語句可以引入其他類
import語句只能出現在package語句之下,class定義的語句之上
語法:
import 全類名;
java.lang;軟件包下所有類不需要手動導入,系統自動導入
關於訪問控制權限修飾符
private 只能在本類中訪問
缺省 本類,同一個包下可以訪問,不同包下不行
protected 本類,同一個包下可以訪問,不同包下不行,但是可以在子類中訪問
public 可以在任何位置訪問
因此,類只能用public或者缺省方式
關於內部類
內部類分爲:靜態內部類、成員內部類、局部內部類、匿名內部類
內部類的重要作用:可以訪問外部類的私有數據
靜態內部類:
1.靜態內部類可以等同看做靜態變量
2.靜態內部類可以直接訪問外部類的靜態數據,無法直接訪問成員
3.靜態內部類可以用訪問控制權限的修飾符修飾(所有的都能用)
4.創建靜態內部類對象的方式:外部類名.內部類名 引用 = new 外部類名.內部類名();
成員內部類:
1.成員內部類可以等同看做成員變量
2.成員內部類可以訪問外部類所有的數據
3.靜態內部類可以用訪問控制權限的修飾符修飾(所有的都能用)
4.創建成員內部類對象的方式:外部類名.內部類名 引用 = new 外部類名().new 內部類名();
5.成員內部類中不能有靜態聲明
局部內部類:
1.局部內部類可以等同看做局部變量
2.局部內部類可以訪問外部類所有的數據
3.局部內部類不能用訪問控制權限的修飾符修飾
4.局部內部類中數據的調用必須在該類所在的方法中調用
5.局部內部類中不能有靜態聲明
6.局部內部類在訪問局部變量的時候,局部變量必須使用final修飾
匿名內部類:
1.匿名內部類指的是沒有名字的局部內部類
2.匿名內部類的格式:
new 接口名(){需要實現的方法}
3.匿名內部類可以直接訪問外部類的靜態數據,無法直接訪問成員
4.匿名內部類中不能有靜態聲明
類和類之間的關係
1、泛化關係:類和類之間的繼承關係及接口與接口之間的繼承關係
2、實現關係:類對接口的實現
3、關聯關係:類與類之間的連接,一個類可以知道另一個類的屬性和方法,即在當前類中含有其他類的引用,在java語言中使用成員變量體現

class Me{
    String name;
    Friend f;//Friend是另一個類,則MeFriend就是關聯關係
    }

4.聚合關係:是關聯關係的一種,是較強的關聯關係,是整體和部分的關係,如:汽車和 輪胎,它與關聯關係不同,關聯關係的類處在同一個層次上,而聚合關係的類處在不平等的層次上,一個代表整體,一個代表部分,在java 語言中使用實例變量體現

public class  ClassRoom { //ClassRoom和List屬於關聯關係,在同一個層次上
    List<Student> stu;//ClassRoom和Student是聚合關係,一個是整體,一個是部分
    }
    public class  Student {     
     }

5.合成關係:是關係的一種,比聚合關係強的關聯關係,如:人和四肢,整體對象決定部分對象的生命週期,部分對象每一時刻只與一個對象發生合成關係,在 java 語言中使用實例變量體現

public class  Person { //Person和List屬於關聯關係,在同一個層次上
    List<Body> b;//Person和Body是合成關係,person是整體,body是部分,整體和部分緊密相連
    }
    public class  Body {     
     }

6.依賴關係:依賴關係是比關聯關係弱的關係,在 java 語言中體現爲返回值,參數,局部變量和靜態方法調用

public class Test{
    public void m1(){
    //局部變量
    User u=new User();//依賴關係
    }
    }
    class User{}

is a,is like a,has a
is a:繼承關係,如Dog is a Animal
is like a:實現關係,如B is like a A,其中A是接口B是類
has a:關聯關係,如A has a B,其中A和B都是類,且A類中有B類的引用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章