1. 程式人生 > >javaSE基礎知識(畢向東視訊筆記)

javaSE基礎知識(畢向東視訊筆記)

程式碼僅僅是你思想的一種體現形式。

知識預備:

軟體開發

軟體:一系列按照特定順序組織的計算機資料和指令的集合.

常用的軟體;

系統軟體(DOS,windows,Linux等)

應用軟體(掃雷,迅雷,QQ等)

什麼是開發?

製作軟體

人機互動

軟體的出現實現了人與計算機之間的更好的互動.

互動方式:圖形化介面GUI簡單直觀,,易於接受,容易上手操作.

命令列方式:CLI需要有個控制檯,輸入特定的指令,讓計算機完成一個操作,較為麻煩,,需要記錄一些命令.

什麼是計算機語言?

語言:是人與人之間用於溝通的一種方式。

計算機語言:人與計算機交流的方式,如:c、c++、java等。

java語言的三種技術架構

1,J2EE企業版(主要針對web應用程式開發)

2,J2SE標準版(開發普通桌面和商務應用)

3,J2ME小型版(開發電子消費產品和嵌入式裝置,如手機中的應用程式)

java語言的特點:跨平臺性

java語言的環境搭建:

JRE java執行環境

JDK java開發工具包(javac.exe編譯工具、java.exe打包工具)

總之:使用JDK開發完成的java程式,交給JRE去執行。

dos命令列:

dir:列出當前目錄下的檔案以及資料夾。

md:建立目錄

rd:刪除目錄

cd:進入指定目錄

cd..:退回到上一級目錄

cd\:退回到根目錄

del:刪除檔案

exit:退出dos命令列

help:幫助

cls:清屏

set:修改path環境變數

set path:檢視path環境變數

java語言基礎:

關鍵字運算子識別符號語句註釋函式常量和變數陣列

語言:    

1,表現形式

2,什麼時候用

藍色關鍵字紅色已有的類

class用於定義類

void沒有返回值

用於定義訪問許可權修飾符的關鍵字

private(私有)       protected(受保護)    public(公有)

用於定義類,函式,變數修飾符的關鍵字

abstract(抽象)   final(最終)    static(靜態)    synchronized(同步)

用於定義類與類之間關係的關鍵字

extends    implements

用於定義建立例項及引用例項,判斷例項的關鍵字

new    this    super    instanceof(用於判斷物件的具體型別)

用於異常處理的關鍵字

try    catch    finally    throw    throws

用於包的關鍵字

package    import

其他修飾符關鍵字

native    stricffp    transient    volatile    assert

類名:首字母大寫、駝峰結構。

識別符號

在程式中自定義的一些名稱

由26個英文字母的大小寫、數字0~9、符號_$組成。

定義合法識別符號規則:

1,由數字、字母、下劃線組成

2數字不可以開頭。

3,不可以使用關鍵字。

java中嚴格區分大小寫。

注意:為了提高閱讀性,名稱要儘量有意義。

註釋

單行註釋://註釋文字

多行註釋:/*註釋文字*/

文件註釋:/**註釋文字*/

註釋的作用:可以進行程式的除錯

javadoc.exe可以提取java檔案中的文件註釋

常量:表示不能改變的數值

java中常量的分類:

1,整數常量,所有整數。

2,小數常量,所有小數。

3,布林(boolean)型常量,兩個值true和false

4,字元常量,將一個數字字母或者符號用單引號標識

5,字串常量,將一個或多個字元用雙引號標識

6,null常量代表不確定的物件(注意空,零,無的區別)

對於整數:有四種表現形式

二進位制    八進位制    十六進位制    十進位制(計算機常用的為前三種)

變數

記憶體中的一個儲存區域

該區域有自己的名稱(變數名)和型別(資料型別

該區域的資料可以在同一類型範圍內不斷變化

為什麼要定義變數?

用來不斷的存放同一型別的常量並可以重複使用

使用變數注意:

變數的作用範圍(一對{}之間有效)

初始化值:

定義變數的格式

資料型別變數名=初始化值;

注:格式是固定的,記住格式,以不變應萬變

理解:變數如同數學中的未知數

資料型別

基本資料型別

數值型

整數型別byte    short    int    long

浮點型別float    double

字元型char

布林型boolean

引用資料型別

類class

介面 interface

陣列[ ]

整數預設:int

小數預設:double

注意:自動型別提升與強制型別轉換

^(異或):一個數異或同一個數兩次,結果還是這個數(可用來交換兩變數的值,而無需使用中間變數,可以少用一個儲存空間,但在實際開發中可讀性較差,不推薦使用,作為了解即可)

<<(左移):幾位其實就是該資料乘以2的幾次方,可以完成2的次冪運算

>>(右移):其實就是該資料除以2的幾次冪,被右移數為負數,結果為負數

>>>(無符號右移):資料進行右移時,高位出現的空位,無論原高位是什麼,空位都用0補齊

提高程式碼的健壯性

提高程式碼的複用性

if和switch的應用

if

1,對具體的值進行判斷

2,對區間判斷

3,對運算結果是boolean型別的表示式進行判斷

switch

1,對具體的值進行判斷

2,值的個數通常是固定的

對於幾個固定的值判斷,建議使用switch語句,因為switch語句會將具體的答案都載入進記憶體,效率高一點

什麼時候使用迴圈結構呢?

當對某些程式碼執行很多次時,使用迴圈結構完成

當對一個條件進行一次判斷時,可以使用if語句

當對一個條件進行多次判斷時,可以使用while語句

注意:在使用迴圈時,一定要明確哪些語句需要參與迴圈,哪些不需要迴圈,通常情況下,需要定義條件,需要控制次數

轉義字元:\n換行\t 製表符\b 退格\r 按下回車鍵

break(跳出)

應用範圍:選擇結構和迴圈結構(可以標號)

continue(繼續)

應用範圍:迴圈結構

方法名:第一個單詞小寫,後面的單詞首字母大寫

記憶體的劃分

1暫存器

2本地方法區

3方法區

4棧記憶體(儲存的都是區域性變數)變數所屬的作用域一旦結束,該變數就自動釋放

5堆記憶體儲存的是陣列和物件(其實陣列就是物件)凡事new建立的都在堆中

特點:

1.每個實體都有首地址

2.堆記憶體中的每一個變數都有預設初始化值,根據型別的不同而不同,整數是0,小數0.0或0.0f,boolean型是false,char是\u0000

3.垃圾回收機制

常見錯誤提示:

ArrayIndexoutofBoundsExceppption陣列索引超出範圍當訪問到陣列中不存在的角標時,就會發生該異常

NullpointerExceppption 空指標異常當引用型變數沒有任何實體指向時,還在用其操作實體,就會發生該異常

[I@c171164(實體的型別雜湊值)

new也是運算子

陣列常見操作

1獲取最值(最大值 最小值)

2排序    Arrays.sort()排序 通常情況下最快的排序:希爾排序(即直接插入排序的優化版本)

3折半查詢(二分查詢)    Arrays.binarysearch()二分查詢如果元素不存在,就返回元素的插入點變成負數-1

什麼時候使用陣列?

如果資料出現了對應關係,而且對應關係的一方是有序的數字編號,並作為角標使用,這時就必須想到陣列

就可以將這些資料儲存到陣列中

根據運算的結果作為角標直接去查陣列中對應的元素即可

這種方式稱為:查表法

Integer.toBinaryString十進位制轉為二進位制

Integer.toOctalString十進位制轉為八進位制

Integer.toHexString十進位制轉為十六進位制

面向物件的三個特點:

1.封裝

2.繼承

3.多型

成員分為兩種:

1.成員變數(屬性)

2.成員函式(行為)

定義類其實就是定義類中的成員

成員變數和區域性變數的區別:

1.成員變數定義在類中,整個類中都可以訪問

區域性變數定義在函式、語句、區域性程式碼塊中,只在所屬的區域有效

2.成員變數存在於堆記憶體的物件中

區域性變數存在於棧記憶體的方法中

3.成員變數隨著物件的建立而存在,隨著物件的消失而消失

區域性變數隨著所屬區域的執行而存在,隨著所屬區域的結束而釋放

4.成員變數都有預設初始化值

區域性變數沒有預設初始化值

new A();匿名物件 其實就是定義物件的簡寫格式

new A().fun();當物件對方法僅進行一次呼叫的時候,就可以簡化成匿名物件

show(new A);匿名物件可以作為實際引數進行傳遞

封裝:是指隱藏物件的屬性和實現細節 僅對外提供公共訪問方式

好處:

1.將變化隔離

2.便於使用

3.提高重用性

4.提高安全性

封裝原則:將不需要對外提供的內容都隱藏起來

把屬性都隱藏 提供公共方法對其訪問

private:私有  是一個許可權修飾符 用於修飾成員

私有的內容只在本類中存放

注意:私有僅僅是封裝的一種體現而已

私有就是封裝 但封裝不僅僅是私有 函式也是封裝

建構函式

特點:函式名與類名相同

不用定義返回值型別

沒有具體的返回值

作用:給物件進行初始化

建構函式在new物件的時候就已經被呼叫了

建立物件都必須要通過建構函式初始化

一個類中如果沒有定義過建構函式 那麼該類中會有一個預設的空引數建構函式  如果在類中定義了指定的建構函式 那麼類中的預設建構函式就沒有了

一般函式和建構函式有什麼區別呢?

建構函式:物件建立時  就會呼叫與之對應的建構函式 對物件進行初始化

一般函式:物件建立後  需要該函式功能時才呼叫

建構函式:物件建立時  會呼叫且只調用一次

一般函式:物件建立後  可以被呼叫多次

什麼時候定義建構函式呢?

在描述事物時 該事物一存在就具備一些內容  這些內容都定義在建構函式中  建構函式可以過載

this這個物件的

this 代表物件  代表哪個物件呢?當前物件

this就是所在函式所屬物件的引用

簡單說 哪個物件呼叫了this所在函式  this就代表哪個函式

this也可以用於在建構函式中呼叫其他建構函式

注意:只能定義在建構函式的第一行  因為初始化動作要執行

static的特點

1static是一個修飾符 用於修飾成員

2static修飾的成員被所有物件所共享

3static優先於物件存在  因為static成員隨著類的載入就已經存在了

4static修飾的成員多了一種呼叫方式  就可以直接被類名所呼叫

5static修飾的資料是共享資料  物件中儲存的是特有資料  被static修飾的變數稱為靜態變數或類變數

成員變數和靜態變數的區別?

1 兩個變數的生命週期不同

成員變數隨著物件的建立而存在 隨著物件的回收而釋放

靜態變數隨著類的載入而存在 隨著類的消失而消失

2呼叫方式不同

成員變數只能被物件呼叫

靜態變數可以被物件呼叫  還可以被類名呼叫

3別名不同

成員變數也稱為例項變數

靜態變數稱為類變數

4資料儲存位置不同

成員變數資料儲存在堆記憶體的物件中  所以也叫物件的特有資料

靜態變數資料儲存在方法區(靜態區、共享資料區) 所以也叫物件的共享資料

靜態使用的注意事項:

1靜態方法只能訪問靜態成員(非靜態既可以訪問靜態  又可以訪問非靜態)

2靜態方法中不可以定義this或者super關鍵字

3主函式是靜態的

主函式的特殊之處:

1.格式是固定的

2.被jvm所識別和呼叫

public:因為許可權必須是最大的

static:不需要物件

void:主函式沒有具體的返回值

main:函式名 不是關鍵字  只是一個jvm識別的固定的名字

String[ ]  args:這是主函式的引數列表  是一個數組型別的引數  而且元素都是字串型別

靜態什麼時候用?

1.靜態變數

當分析物件中所具備的成員變數的值都是相同的

這時這個成員就可以被靜態修飾

只要資料在物件中都是不同的 就是物件的特有資料 必須儲存在物件中 是非靜態的

如果是相同的資料  物件不需要做修改  只需要使用即可  不需要儲存在物件中  定義成靜態的

2.靜態函式

函式是否用靜態修飾 就參考一點  就是該函式功能是否有訪問到物件中的特有資料

簡單點說  從原始碼看 該功能是否需要訪問非靜態的成員變數  如果需要  該功能就是非靜態的

但是非靜態需要被物件呼叫 而僅建立物件呼叫非靜態的沒有訪問特有資料的方法  該物件的建立是沒有意義的

靜態程式碼塊:

隨著類的載入而執行 而且只執行一次

作用:用於給類進行初始化

構造程式碼塊:可以給所有物件進行初始化

建構函式:是給對應的物件進行鍼對性的初始化

該類中的方法都是靜態的  所以該類是不需要建立物件的  為了保證不讓其建立該類物件  可以將建構函式私有化

設計模式(23種)

 對問題行之有效的就解決方式:其實它是一種思想

1.單例設計模式

解決的問題:可以保證一個類在記憶體中物件的唯一性

必須對於多個程式使用同一個配置資訊物件時  就需要保證該物件的唯一性

如何保證物件唯一性呢?

1.不允許其他程式用new建立該類物件

2.在該類中建立一個本類例項

3.對外提供一個方法讓其他程式可以獲取該物件

步驟:

1.私有化該類的建構函式

2.通過new在本類中建立一個本類物件

3.定義一個公有的方法 將建立的物件返回

餓漢式用於開發  懶漢式(延遲載入)用於面試

extends 父類名(超類、基類)

繼承的好處:

1.提高了程式碼的複用性

2.讓類與類之間產生了關係  給第三個特徵 多型 提供了前提

java中支援單繼承 不直接支援多繼承 但對C++中的多繼承機制進行了改良

單繼承:一個子類只能有一個直接父類

多繼承:一個子類可以有多個直接父類(java中不允許進行改良 通過多實現)不直接支援 是因為會產生呼叫的不確定性

java支援多層繼承(多重繼承)

c繼承b  b繼承a  就會出現繼承體系

當要使用過一個繼承體系時

1.檢視該體系中的頂層類  瞭解該體系的基本功能

2.建立體系中的最子類物件  完成功能的使用

什麼時候定義繼承呢?

當類與類之間存在著所屬關係的時候  就定義繼承

x是y中的一種  x  extends  y

所屬關係: is  a  關係

在子父類中  成員的特點體現

1.成員變數

當本類的成員和區域性變數同名用this區分

當子父類中的成員變數同名用super區分

this和super的用法很相似

this代表一個本類物件的引用

super代表一個父類空間

2.成員函式

當子父類中出現成員函式一模一樣的情況  會執行子類的函式

這種現象 稱為覆蓋操作  這是函式在子父類中的特性

函式的兩個特性:

1.過載  同一個類中

2.覆蓋  子類中也稱為重寫 覆寫

覆蓋注意事項:

1.子類方法覆蓋父類方法時 子類的許可權必須大於等於父類的許可權

2.靜態只能覆蓋靜態  或被靜態覆蓋

什麼時候使用覆蓋操作?

當對一個類進行子類的擴充套件時  子類需要保留父類的功能宣告

但是要定義子類中該功能的特有內容時 就使用覆蓋操作完成

3.建構函式

在子類構造物件時  發現 訪問 子類建構函式時 父類也運行了 為什麼呢?

原因是:在子類的建構函式中的第一行有一個預設的隱式語句:super();//呼叫的就是父類中的空引數的建構函式

子類的例項化過程:子類中所有的建構函式預設都會訪問父類中的空引數的建構函式

為什麼子類例項化的時候要訪問父類中的建構函式呢?

那是因為子類繼承了父類 獲取到了父類中的內容(屬性)所以在使用父類內容之前  要先看父類是如何對自己的內容初始化的 所以子類在構造物件時 必須訪問父類中的建構函式

為了完成這個必須的動作 就在子類的建構函式中加入了super()語句  如果父類中沒有定義空引數建構函式 那麼子類的建構函式必須用super明確要呼叫父類中哪個建構函式  同時子類建構函式中如果使用this呼叫了本類建構函式時  那麼this就沒有了  因為super和this都只能定義在第一行

注意:super語句必須要定義在子類建構函式的第一行  因為父類的初始化動作要先完成

一個物件例項化過程:

1jvm會讀取指定的路徑下的*.class檔案 並載入進記憶體  並會先載入*的父類(如果有直接父類的情況下)

2在堆記憶體中開闢空間 分配地址

3並在物件空間中 對物件中的屬性進行預設初始化

4呼叫對應的建構函式進行初始化

5在建構函式中 第一行會先呼叫父類中的建構函式進行初始化

6父類初始化完畢後 再對子類的屬性進行顯示初始化

7在進行子類建構函式的特定初始化

8初始化完畢後 將地址值賦值給引用變數

繼承弊端:打破了封裝性

final關鍵字:

1.final是一個修飾符 可以修飾類 方法 變數

2.final修飾的類不可以被繼承

3.final修飾的方法不可以被覆蓋

4.final修飾的變數是一個常量 只能賦值一次

為什麼要用final修飾變數 其實在程式中如果一個數據是固定的 那麼直接使用這個資料就可以了 但是這樣閱讀性差 所以給該資料起個名稱 而且這個變數名稱的值不能變化 所以加上final固定

寫法規法:常量所有字母都大寫 多個單詞 中間用_連線

抽象類:

抽象的概念:籠統、模糊、不具體

抽象的特點:

1.方法只有宣告 沒有實現時 該方法就是抽象方法 需要被abstract修飾 抽象方法必須定義在抽象類中 該類必須也被abstract修飾

2.抽象類不可以被例項化 為什麼?

因為呼叫抽象方法沒意義

3.抽象類必須有其子類覆蓋了所有的抽象方法後 該子類才可以例項化 否則 這個子類還是抽象類

抽象類中有建構函式嗎?

有 用於給子類物件進行初始化

抽象類可以不定義抽象方法嗎?

可以的  但是很少見 目的就是不讓該類建立物件 AWT的介面卡就是這種類 通常這個類中的方法有方法體 但是卻沒有內容

抽象關鍵字不可以和哪些關鍵字共存?

private因為抽象方法需要被覆蓋

static因為沒有意義

final因為不能被繼承類和被覆蓋抽象方法

抽象類和一般類的異同點:

相同點:抽象類和一般類都是用來描述事物的 都在內部定義了成員

不同點

1.一般類有足夠的資訊描述事物

抽象類描述事物的資訊有可能不足

2.一般類中不能定義抽象方法 只能定義非抽象方法

抽象類中可以定義抽象方法 也可以定義非抽象方法

3.一般類可以被例項化

抽象類不可以被例項化

抽象類一定是個父類嗎?

是的   因為需要子類覆蓋其方法後才可以對子類例項化

當一個抽象類中的方法都是抽象的時候 這時可以將該抽象類用另一種形式定義和表示 就是介面 interface

定義介面使用的關鍵字不是class 時interface

介面中常見的成員:(這些成員都有固定的修飾符)

1.全域性常量:public static  final

2.抽象方法:public abstract

由此得出結論 介面中的成員都是公共的許可權

類與類之間是繼承關係 類與介面之間是實現關係(implements)

介面不可以例項化

只能由實現了介面的子類並覆蓋了介面中所有的抽象方法後  該子類才可以例項化 否則 這個子類就是一個抽象類

在java中不直接支援多繼承 因為會出現呼叫的不確定性

所以java將多繼承機制進行改良 在java中變成了多實現

多實現:一個類可以實現多個介面

介面的出現避免了單繼承的侷限性

介面可以繼承介面 而且介面可以多繼承

介面的特點:

介面是對外暴露的規則

介面是程式的功能擴充套件

介面的出現降低了耦合性

介面可以用來多實現

類與介面之間是實現關係 而且類可以繼承一個類的同時實現多個介面

介面與介面之間可以有繼承關係

多型的定義:某一類事物的多種存在形態(簡單說 就是一個物件對應著不同型別)

多型在程式碼中的體現

父類或者介面的引用指向其子類的物件

多型的好處:

提高了程式碼的擴充套件性 前期定義的程式碼可以使用後期的內容

多型的弊端(侷限性)

前期定義的內容不能使用(呼叫)後期子類的特有內容

多型的前提:

1.必須有關係 繼承 實現

2.要有覆蓋

向上轉型:將子型別隱藏 就不能使用子類的特有方法了

向下轉型:目的是為了使用子類中的特有方法

注意:對於轉型 自始至終都是子類物件在做著型別的變化

常見異常:classcastException        //型別轉換異常

instanceof:用於判斷物件的具體型別 只能用於引用資料型別判斷,通常在向下轉型前用於健壯性的判斷

多型時成員的特點:

1.成員變數

編譯時:參考引用型別變數所屬的類中是否有呼叫的成員變數 有 編譯直接通過 沒有 編譯失敗

執行時:參考引用型別變數所屬的類中是否有呼叫的成員變數  並執行該所屬類中的成員變數

簡單說:編譯和執行都參考符號的左邊

2.成員函式

編譯時:參考引用型別變數所屬的類中是否有呼叫的函式 有 編譯直接通過 沒有 編譯失敗

執行時:參考的是物件所屬的類中是否有呼叫的函式

簡單說:編譯看左邊 執行看右邊

3.靜態函式

編譯時:參考引用型別變數所屬的類中是否有呼叫的靜態方法 

執行時:參考引用型別變數所屬的類中是否有呼叫的靜態方法 

簡單說:編譯和執行都看左邊 其實對於靜態方法 是不需要物件的 直接用類名呼叫即可

內部類

將一個類定義在另一個類的裡面 對裡面的那個類就稱為內部類(內建類、巢狀類)

訪問特點

內部類可以直接訪問外部類中的成員 包括私有成員

而外部類要訪問內部類中的成員 必須要建立內部類的物件

一般用於類的設計

分析事物時 發現該事物的描述中還有事物 而且這個事物還在訪問被描述事物的內容 這時就把還有的事物定義成內部類來描述

如果內部類是靜態的 相當於一個外部類

如果內部類中定義了靜態成員 該內部類也必須是靜態的

為什麼內部類能直接訪問外部類中的成員呢?

那是因為內部類持有了外部類的引用 外部類名.this

內部類可以存放在區域性位置上

內部類在區域性位置上 只能訪問區域性中被final修飾的區域性變數

匿名內部類:就是內部類的簡寫格式

使用匿名內部類必須有前提:內部類必須繼承或者實現一個外部類或者介面

匿名內部類:其實就是一個匿名子類物件

格式:new 父類or介面(){子類內容}

通常的使用場景之一

當函式引數是介面型別時  而且介面中的方法不超過三個  可以用匿名內部類作為實際引數進行傳遞

因為匿名內部類這個子類物件被向上轉型為了Object型別  這樣就不能再使用子類的特有方法了

異常Exception

異常的體系

Throwable可拋

Error(錯誤)通常出現重大問題 如:執行的類不存在或者記憶體溢位等 不編寫針對程式碼對其處理

Exception(異常)在執行時執行出現的一起情況 可以通過try catch finally 

ExceptionError的子類名都是以父類名作為字尾

異常:是在執行時期發生的不正常情況

在java中用類的形式對不正常情況進行了描述和封裝物件

描述不正常情況的類,就稱為異常類

以前正常流程程式碼和問題程式碼相結合

現在將正常流程程式碼和問題處理程式碼分離   提高閱讀性

其實異常就是java通過面向物件的思想將問題封裝成了物件

用異常類對其進行描述

不同的問題用不同的類進行具體的描述  比如角標越界  空指標等

問題很多 意味著描述的類也很多

將其共性進行向上抽取  形成了異常體系

最終問題(不正常情況)就分成了兩大類 Error  exception

Throwable:無論是error  還是Exception  問題發生就應該可以丟擲 讓呼叫者知道並處理   //該體系的特點就在於Throwable及其所有的子類都具有可拋性

可拋性到底是指什麼呢?怎麼體現可拋性呢?

其實是通過兩個關鍵字來體現的

throws  throw   凡是可以被這兩個關鍵字所操作的類和物件都具備可拋性

1.一般不可處理的:Error

特點:是由jvm丟擲的嚴重性的問題

這種問題發生 一般不針對性處理 直接修改程式

2.可以處理的:Exception

該體系的特點:

子類的字尾都是用其父類名作為字尾  閱讀性很強

負數角標這種異常在java中並沒有定義過

那就按照java異常的建立思想 面向物件 將負數角標進行自定義描述  並封裝成物件 

這種自定義的問題描述稱為自定義異常

注意:如果過讓一個類稱為異常類  必須要繼承異常體系 因為只有成為異常體系的子類才有資格具備可拋性  才可以被兩個關鍵字所操作  throw  throws

異常的分類:

1.編譯時被檢測異常:只要是Exception和其子類都是 出了特殊子類RuntimeException體系

這種問題一旦出現 希望在編譯時就進行檢測 讓這種問題有對應的處理方式  這樣的問題都可以針對性的處理

2.編譯時不檢測異常(執行時異常):就是Exception中的RuntimeException和其子類

這種問題的發生 無法讓功能繼續 運算無法進行 更多是因為呼叫者的原因導致的  或者引發了內部狀態的改變導致的 那麼這種問題一般不處理 直接接編譯通過 在執行時 讓呼叫者呼叫時的程式強制停止 讓呼叫者對程式碼進行修正 所以自定義異常時 要麼繼成功Exception 要麼繼承RuntimeException

throws和throw的區別

1.throws使用在函式上

throw使用在函式內

2.throws丟擲的時異常類 可以丟擲多個 用逗號隔開

throw丟擲的時異常物件

異常處理的描述形式:

這是可以對異常進行鍼對性處理的方式

具體格式是:

try{

//需要被檢測異常的程式碼

}

catch(異常類 變數){//該變數用於接收發生的異常物件

//處理異常的程式碼

}

finally{

//一定會被執行的程式碼

}

多catch 父類的catch放在最下面

異常處理的原則:

1.函式內部如果丟擲需要檢測的異常 那麼函式上必須要宣告 否則必須在函式內用try catch 捕捉 否則編譯失敗

2.如果呼叫到了宣告異常的函式 要麼try catch 要麼throws 否則編譯失敗

3.什麼時候catch 什麼時候throws呢?

功能內部可以解決 用catch

解決不了 用throws告訴呼叫者 由呼叫者解決

4.一個功能如果丟擲了多個異常 那麼呼叫時 必須有對應多個catch進行鍼對性的處理 內部有幾個需要檢測的異常 就拋幾個異常 丟擲幾個 就catch幾個

System.exit(0);//退出jvm

finally   //通常用於關閉(釋放)資源

trycatchfinally程式碼塊的組合特點:

1.trycatchfinally

2.trycatch(多個)當沒有必要資源需要釋放時 可以不用定義finally

3.tryfinally異常無法直接catch處理 但是資源需要關閉

異常的注意事項:

1.子類在覆蓋父類方法時 父類的方法如果丟擲了異常 那麼子類的方法只能丟擲父類的異常或者該異常的子類

2.如果過父類丟擲多個異常 那麼子類只能丟擲父類異常的子集

簡單說:子類覆蓋父類只能丟擲父類的異常或子類或者子集

注意:如果父類的方法沒有丟擲異常 那麼子類覆蓋時絕對不能拋 就只能try

Object:所有類的根類

equals():比較兩個物件是否相等(判斷地址還有內容)

一般都會覆蓋此方法,根據物件的特有內容建立判斷物件是否相同的依據

注意:當此方法被重寫時,通常有必要重寫hashCode方法,以維護hashCode

hashCode():返回此物件的一個雜湊碼值

該方法的常規協定:該協定宣告相等物件必須具有相等的雜湊碼

getClass()返回表示此物件執行時類的class物件

getName()以String的形式返回此Class物件所表示的實體(類,介面,陣列類,基本型別或void)名稱

toString()返回該物件的字元表示

package(包)

對類檔案進行分類管理

給類提供多層名稱空間

寫在程式的第一行

類名的全稱是:包名.類名

包也是一種封裝的形式

protected(保護)

各種情況下的訪問許可權

publicprotecteddefaultprivate
同一類中okokokok
同一個包中okokok
子類中okok
不同包中ok

import(匯入)

導包的原則:用到那個類,就匯入哪個類

jar:java的壓縮包

程序:正在進行中的程式

執行緒:就是程序中一個負責程式執行的控制單元(執行路徑),一個程序中可以有多個執行路徑,稱為多執行緒

一個程序中至少有一個執行緒

開啟多個執行緒是為了同時執行多部分程式碼

每一個執行緒都有自己執行的內容,這個內容可以稱為執行緒要執行的任務

多執行緒的好處:解決了多部分同時執行的問題

多執行緒的弊端:執行緒太多,會導致效率降低

其實應用程式的執行都是cpu在做著快速的切換來完成的,這個切換是隨機的

jvm啟動時就啟動了多個執行緒,至少有兩個執行緒是可以分析出來的

1.執行main函式的執行緒,該執行緒的任務程式碼都定義在main函式中

2.負責垃圾回收的執行緒

如何建立一個執行緒呢?

步驟

1.定義一個類繼承Thread類

2.覆蓋Thread類中的run方法

3.直接建立Thread的子類物件 建立執行緒

4.呼叫start方法開啟執行緒的任務run方法執行

建立執行緒的目的是為了開啟一條新的執行路線,去執行指定的程式碼塊和其他程式碼,實現同時執行,而執行的指定程式碼就是這個執行路徑的任務

jvm建立的主執行緒的任務都定義在了主函式中,而自定義的執行緒他的任務在哪兒呢?

Thread類用於描述執行緒,執行緒是需要任務的,所以Thread類也有對任務的描述,這個任務就通過Thread類中的run方法來體現,也就是說run方法就是封裝自定義執行緒執行任務的函式,run方法中定義的就是執行緒要執行的任務程式碼

開啟執行緒是為了執行指定程式碼,所以只有繼承Thread類並複寫run方法,將執行的程式碼定義在run方法中即可

start()開啟執行緒並呼叫run方法

可以通過Thread的getName()獲取執行緒的名字

Thread-編號(從0開始)

主執行緒的名字就是main

執行緒的四種狀態:1.被建立2.執行3.凍結.4.消亡

sleep()睡眠    sleep方法需要指定睡眠時間,單位是毫秒

wait()等待

notify()喚醒

stop()結束執行緒(較暴力)

cpu的執行資格:可以被cpu處理,在處理佇列中排隊

cpu的執行權:正在被cpu處理

執行:具備著執行資格並具備著執行權

凍結:釋放執行權並釋放執行資格

臨時阻塞狀態(就緒狀態):具備執行資格,但不具備執行權,正在等待執行權

建立執行緒的第二種方式:實現Runnable介面

步驟

1.定義類實現Runnable介面

2.覆蓋介面中的run方法,將執行緒的任務程式碼封裝到run方法中

3.通過Thread類建立執行緒物件,並將Runnable介面的子類物件作為Thread類的建構函式的引數進行傳遞

為什麼?因為執行緒的任務都封裝在Runnable介面子類物件的run方法中,所以要線上程物件建立時就必須明確要執行的任務

4.呼叫執行緒物件的start方法開啟執行緒

實現Runnable介面的好處:

1.將執行緒的任務從執行緒的子類中分離出來,進行了單獨的封裝,按照面向物件的思想將任務封裝成物件

2.避免了java單繼承的侷限性,所以,建立執行緒的第二種方式較為常用

執行緒安全問題產生的原因:

1.多個執行緒在操作共享的資料

2.操作共享資料的執行緒程式碼有多條

當一個執行緒在執行操作共享資料的多條程式碼的過程中,其他執行緒參與了運算,就會導致執行緒安全問題的產生

解決思路:

就是將多條操作共享資料的執行緒程式碼封裝起來,當有執行緒在執行這些程式碼的時候,其他執行緒是不可以參與運算的,必須要當前執行緒把這些程式碼都執行完畢後,其他執行緒才可以參與運算,在java中,同步程式碼塊就可以解決這個問題

同步程式碼塊的格式:

synchronize(物件)

{

需要被同步的程式碼

}

同步的好處:解決了執行緒的安全問題

同步的弊端:相對降低了效率,因為同步外的執行緒都會判斷同步鎖

同步的前提:同步中必須有多個執行緒並使用同一個鎖

同步函式

同步函式使用的鎖是this

同步函式和同步程式碼塊的區別:

1.同步函式的鎖是固定的this

2.同步程式碼塊的鎖是任意的物件

建議使用同步程式碼塊

靜態的同步函式使用的鎖是該函式所屬位元組碼檔案物件,可以用getClass方法獲取,也可以用當前類名.class來表示

多執行緒下的單例設計模式(嘰哩哇啦%#$^%@)

死鎖常見於:

1.同步的巢狀

2.執行緒間通訊(多個執行緒在處理同一資源,但是任務卻不同)

等待/喚醒機制

涉及的方法:

1.wait():讓執行緒處於凍結狀態,被wait的執行緒會被儲存到執行緒池中

2.notify()喚醒執行緒池中一個執行緒(任意)

3.notifyAll()喚醒執行緒池中的所有執行緒

注:這些方法都必須定義在同步中,因為這些方法是用於操作執行緒狀態的方法,必須要明確到底操作的是哪個鎖上的執行緒

為什麼操作執行緒的方法wait    notify    notifyAll都定義在了Object類中?

因為這些方法是監視器的方法,監視器其實就是鎖,鎖可以是任意的物件,任意的物件呼叫的方式一定定義在Object類中

生產者/消費者模式(所生產者/多消費者問題)

嘰哩哇啦%#%

while判斷標記,解決了執行緒獲取執行權後,是否要執行!

notifyAll解決了,本方執行緒一定會喚醒對方執行緒

if判斷標記,只有一次,會導致不該執行的程式運行了,出現了資料錯誤的情況

notify()只能喚醒一個執行緒,如果本方喚醒了本方,沒有意義,而且while判斷標記+notify會導致死鎖

jdk1.5以後將同步和鎖封裝成了物件,並將操作鎖的隱式方式定義到了該物件中,從而將隱式動作變成了顯式動作

lock.lock()獲取鎖

lock.unlock()釋放鎖,通常需要定義到finally程式碼塊中

Lock lock = new ReentrantLock();//建立一個鎖物件
Condition con = lock.newCondtion();//通過已有的鎖獲取該鎖上的監視器物件
Condition con1 = lock.newCondtion();//通過已有的鎖獲取該鎖上的監視器物件,一組監視生產者,一組監視消費者
Condition con2 = lock.newCondtion();//通過已有的鎖獲取該鎖上的監視器物件,一組監視生產者,一組監視消費者
await()等待
signal()喚醒一個等待執行緒

signalAll()喚醒所有等待執行緒

Lock介面:出現替代了同步程式碼塊或者同步函式,將同步的隱式鎖操作變成顯示鎖操作,同時更為靈活,可以一個鎖加上多組監視器

Condition介面:出現替代了Object中的wait    notify    notifyAll方法,將這些監視器方法單獨進行了封裝,變成condition監視器物件,可以與任意鎖進行組合

wait和sleep區別?

1.wait可以指定時間,也可以不指定,sleep必須指定時間

2.在同步中,對cpu執行權和鎖的處理不同

wait:釋放執行權,釋放鎖

sleep:是執行權,不釋放鎖

停止執行緒

1.定義迴圈結束標記,因為執行緒執行程式碼一般都是迴圈,只要控制了迴圈即可

2.使用interrupt(中斷)方法,該方法是結束執行緒的凍結狀態,使執行緒回到執行狀態

注:stop方法已經廢棄,不再使用,因為太過暴力,會導致資料不同步

停止執行緒的方法

1.stop方法

2.run方法結束

怎麼控制執行緒的任務結束呢?

任務中都會有迴圈結構,只要控制住迴圈就可以結束任務,控制迴圈通常就用定義判斷標記來完成,但是如果執行緒處於了凍結狀態,無法讀取標記,如何結束呢?

可以使用interrupt()方法將執行緒從凍結狀態強制恢復到執行狀態中來,讓執行緒具備cpu執行資格

當使用強制動作會發生InterruptedException,記得要處理

執行緒類的其他方法

setPriority(int num)更改執行緒的優先順序

setDaemon(boolean b)將該執行緒標記為守護執行緒或使用者執行緒