黑馬程式設計師_畢向東JAVA基礎_設計模式&異常處理機制

不倒的青春發表於2013-06-21

---------------------- ASP.Net+Android+IO開發S.Net培訓、期待與您交流! ----------------------

單例設計模式

設計模式:解決某一類問題最行之有效的方法。

單例設計模式:解決一個類在記憶體只存在一個物件。分為餓漢式和懶漢式。

想要保證物件的:

1.為了避免其他程式過多建立該物件。先禁止其他程式建立該類物件。

2.為了讓其他程式設計師可以訪問到該類物件,只好在本類中,自定義一個物件。

3.為了方便其他程式對自定義物件的訪問,可以對外提供一些訪問方式。

實現:

1.將建構函式私有化,無法建立例項物件。

2.在類中建立一個本類物件。

3.提供一個方法可以獲取該物件。


對於事物該怎麼描述,就怎麼描述。當需要將該事物的物件保證在記憶體中唯一時,將上述三步加上即可。

<方法呼叫方式有物件和類名(靜態)兩種方式。>單例模式無法建立物件,只能使用靜態呼叫的方法。

餓漢式:先初始化化物件。Single類一進記憶體,物件就被建立了。(建議使用)

class Single
{
	//私有構造方法。
	private Single(){}
	//私有,靜態的類自身的例項物件。
	private static Single s = new Single();
	//呼叫方法。
	public static Single getInstance()
	{
		return s;
	}
}


class SingleDemo 
{
	public static void main(String[] args) 
	{
		Single ss = Single.getInstance();
	}
}

變種形式:

class Single
{  
       
	//私有,靜態的類自身例項   
	private static Single s = null; 
	//靜態程式碼塊
	static
	{  
		s = new Single();  
	}  
       
	 //私有的構造方法  
	private Single(){}  
       
	//呼叫物件方法。   
	public static Single getInstance()
	{  
        return s;  
    }  
}



懶漢式:

物件是方法被呼叫時才初始化,也叫做物件的延時載入。

Single類進記憶體,物件還沒有存在,只有呼叫了getInstance方法時,才建立物件。

class Single
{
	//私有構造方法。
	private Single(){}
	private static Single s = null;
	//呼叫方法。
	public static Single getInstance()
	{
		if (s == null)
			s = new single();
		return s;
	}
}


class SingleDemo 
{
	public static void main(String[] args) 
	{
		Single ss = Single.getInstance();
	}
}

多執行緒併發需同步

class Single  
{   
     //私有構造方法,不允許其他類建立物件   
     private Single(){};  
     private static Single s =null;  
     //提供獲取物件的方法   
     public static Single getInstance()  
     {   
          //提高判斷鎖的效率不讓每次都判斷   
          if(s == null)  
          //多執行緒的同步操作,鎖是自身的位元組碼   
          synchronized (Single.class)   
          {   
                if(s == null)  
                //自己建立物件   
                s =  new Single();     
          }  
          return s;  
     }  
} 

死鎖:多個執行緒同時被阻塞,他們中的一個或者全部都在等待某個資源被釋放。由於執行緒被無限期地堵塞,因此程式不可以正常終止。

  導致死鎖的根源在於不適當地運用“synchronized”關鍵詞來管理執行緒對特定物件的訪問。“synchronized”關鍵詞的作用是,確保在某個時刻只有一個執行緒被允許執行特定的 程式碼塊,因此,被允許執行的執行緒首先必須擁有對變數或物件的排他性的訪問權。當執行緒訪問物件時,執行緒會給物件加鎖,而這個鎖導致其它也想訪問同一物件的執行緒被阻 塞,直至第一個執行緒釋放它加在物件上的鎖。

  由於這個原因,在使用“synchronized”關鍵詞時,很容易出現兩個執行緒互相等待對方做出某個動作的情形。程式碼一是一個導致死鎖的簡單例子。


異常處理機制

異常:就是程式在執行時出現的不正常情況。

異常的由來:問題也是現實生活中的一個具體的事物,也可以通過java類的形式進行描述。並封裝成物件。其實就是對java不正常情況進行描述後物件的體現。

異常的好處:

1.      將問題進行封裝

2.      將正常流程程式碼和問題處理程式碼相分離,方便閱讀。

對於問題劃分兩種:一種是嚴重的問題,一種是非嚴重的。

對於嚴重的。java通過error類進行描述。

對於error一般不編寫針對性的程式碼對其進行處理。

對於非嚴重的。java通過exception類進行描述。

  對於exception可以使用針對性的處理方式處理;比如,資料角標越界等。

無論error或者exception都具有一些共性內容。比如:不正常情況的資訊,引發原因等。

throwable

|--error

|--exception

異常的處理

java提供了特有的語句進行處理。

try
{
	需要被檢測的程式碼;
}
catch (異常類  變數)//多型性!!
{
	處理異常的程式碼: (處理方式)//注意拋幾個異常,這裡面就要寫幾個處理處理方式。
}
finally
{
}
其實JVM預設的異常處理機制,就是在呼叫printStackTrace方法。列印異常的堆疊跟蹤資訊。


對多異常的處理。

1.宣告異常時,建議宣告更為具體的異常。這樣處理的可以更具體。不要定義多餘的。

2.對方宣告幾個異常,就應有幾個catch塊。如果多個catch塊中的異常出現繼承關係,父類異常catch塊放在最下面。

建議:在進行catch處理時,catch中一定要定義具體的處理方式。不要簡單定義一句e.printStackTrace,也不要簡單的定義一句輸出語句。

自定義異常:按照java的物件導向思想,將程式中出現的特有問題進行封裝。

因為專案中會出現特有問題,而這些問題未被java所描述並封裝成物件。所以對於這些特有問題可以按照java的對問題封裝的思想。將特有問題進行自定義的異常封裝。

/*
需求:在本程式中,對於除數是-1,也視為是錯誤的無法進行運算。


當在函式內部出現了throw丟擲異常物件,那麼就必須給對應的處理動作。
要麼在內部try catch處理。要麼在函式上宣告讓呼叫者處理。
一般情況在,函式內部出現異常,函式上需要宣告

發現列印的結果中只有異常的名稱,卻沒有異常的資訊。
因為自定義的異常並未定義資訊。

如何定義異常資訊呢?

因為父類中已經把異常資訊的操作都完成了。所以父類只要在建構函式時,
將異常資訊傳遞給父類通過super語句。那麼就可以直接通過getMessage
方法獲取自定義的異常資訊。

自定義異常:
必須是自定義類繼承Exception.
繼承Exception的原因:異常體系有個特點:因為異常類和異常物件都需要被丟擲。
他們都具備可拋性。這個可拋性是throwable體系中的獨有特點。只有這個體系中
的類和物件,才可被throws和throw所操作。


這個體系:Error  throwable  exception.

throws和 throw的區別:throws使用在函式上。throw使用在函式內。

throws後面跟的是異常類。可以跟多個。用逗號隔開。
throw後面跟的是異常物件。





*/

class FuShuException extends Exception //目的為宣告物件
{
	int value ;

	FuShuException(String msg , int value)//建構函式中傳入msg。
	{
		 super(msg);//通過super語句,傳遞給父類。
		 this.value = value;
	}
	public int getValue()
	{
		return value;
	}
}

class Demo
{
	int div(int a,int b)throws FuShuException//函式內部出現異常,在函式上宣告。
	{
		if(b < 0)
			throw new FuShuException("cddddd",b);//手動通過throw關鍵字,丟擲自定義異常物件
		return a/b;
	}
}

class ExceptionDemo1 
{
	public static void main(String[] args) 
	{
		Demo d = new Demo();
		try
		{
			int x = d.div(4,-1);
			System.out.println("x="+x);
			
		}
		catch (FuShuException e)
		{
			System.out.println(e.toString());
			System.out.println("除數是"+e.getValue());
		}		
	}
}
/* exception中有個特殊的子類異常RuntimeException執行時異常
 如果再函式內容丟擲該異常,函式上可以不用宣告,編譯一樣通過。
 如果再函式上宣告該異常,呼叫者可以不用進行處理。

 之所以不用再函式上宣告,是因為不需要讓呼叫者處理,
 當該異常發生,希望程式停止。因為在執行時,出現了
 無法繼續執行的情況,希望程式停止,對程式碼進行修正。

 自定義異常時:如果該異常的發生時,無法再繼續進行運算,
 就讓自定義異常繼承RuntimException


 對於異常分為兩種:
 1.編譯時被檢測的異常
 2.編譯時不被檢測的異常(執行時異常。RuntimeException以及其子類)


*/


class FuShuException extends RuntimeException //目的為宣告物件
{
	int value ;

	FuShuException(String msg , int value)//建構函式中傳入msg。
	{
		 super(msg);//通過super語句,傳遞給父類。
		 this.value = value;
	}
	public int getValue()
	{
		return value;
	}
}


class Demo
{
	int div(int a,int b)
	{
		
		
		if(b<0)
			throw new FuShuException("負數",b);
		
		if(b==0)
			throw new ArithmeticException("beioddd");

		return a/b;
	}
}
class ExceptionDemo11 
{
	public static void main(String[] args) 
	{
		Demo d = new Demo();

		int x = d.div(4,-1);
		System.out.println("Hello World!");
	}
}

第一種格式:

try{}

catch()

{

}

第二種格式:

try{}

catch()

{

}

finally

{

}

第三種格式:

try{}

finally

{

}

finally存放的是一定會被執行的程式碼;通常同於關閉資源。

finally只有一種情況不會執行。當執行到System.exit(0);fianlly不會執行

如果問題被解決,外部沒有宣告標識,也可以編譯通過。但是如果catch繼續丟擲問題,那麼編譯不通過。

catch是用於處理異常的,如果沒有catch就代表異常沒有處理,如果該異常是檢測時異常,那麼必須宣告。


異常在子父類覆蓋中的體現:

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

Exception

|--AException

|--BException

|--CException

2.如果父類方法丟擲多個異常,那麼子類在覆蓋該方法時,只能丟擲父類的異常的子類。

3.如果父類或者介面的方法中沒有異常丟擲,那麼子類在覆蓋方法時,也不可以丟擲異常。

如果子類方法發生了異常,就必須要進行try處理,絕對不能拋。


異常體系:

體系特點:異常體系中的所有類以及建立的物件都具備可拋性。也就是說可以被throw和throws關鍵字所操作。只有異常體系具備這個特點。

throw和throws的用法:

throw定義在函式內,用於丟擲異常物件。

throws定義在函式上,用於丟擲異常類,可以丟擲多個,用逗號隔開。

當函式內容有throw丟擲異常物件,並未進行try處理。必須要在函式上宣告。

注意:RuntimeException除外,也就是說,函式內如果丟擲RuntimeException異常,函式上可以不用宣告。

如果函式宣告瞭異常,呼叫者需要進行處理。處理方法可以throws,可以try。

異常有兩種:

編譯時被檢測異常:該異常在編譯時,沒有被處理(沒有拋也沒有try),編譯失敗。該異常被標識,代表可以被處理。

執行時異常(編譯時不檢測):在編譯時,不需要處理,編譯器不檢查。該異常的發生,建議不處理,讓程式停止,需要對程式碼進行修正。


不同包中的類如何訪問?

 

包與包之間進行訪問,被訪問的包中的類以及類中的成員,需要public修飾。不同包中的子類還直接可以訪問父類中被protected許可權修飾的成員。

包與包之間只能使用的許可權只有兩種,public protected(只能給子類使用)

 

public

protected

default

private

同一個類中

Ok

Ok

Ok

Ok

同一個包中

Ok

Ok

Ok

 

子類

Ok

Ok

 

 

不同包中

Ok

 

 

 

 

一個.java檔案中不能出現兩個以上的公有類或介面。

 

為了簡化類名的書寫,使用一個關鍵字,import

Import匯入的是包中的類

建議,不要寫萬用字元*。

當匯入不同包中有相同的重名類時,必須加包名。

 

建議定義包名不要重複,可以使用url來完成定義。因為url是唯一的。

 

Java的壓縮包:方便專案攜帶。方便於使用,只要在classpath設定jar路徑就行。

---------------------- ASP.Net+Android+IO開發S.Net培訓、期待與您交流! ----------------------

相關文章