java_day 08:異常(try catch finally異常処理メカニズム)理解と応用


1.異常
1.異常の概要
1.1異常の導入
現実の生活の中で万物は発展と変化の中でいろいろな異常な現象が現れます.
1.2異常発生の原因
**コア:**問題のあるコードが表示された場所で、デフォルトで異常現象を作成して放出し、異常オブジェクトに異常の記述情報をカプセル化し、デフォルトでメソッドの呼び出し者に処理します.
1.4.throwを使用して例外を放出
コードに問題がある場合、throwキーワードを使用して例外の記述情報を含む例外オブジェクトを放出します.
1.5.カスタム例外
需要:学生の年齢に値をつけて、学生の年齢が合法でない時、私達は1つの“年齢の境界を越えて異常です”を投げ出します!解決:javaで提供される例外には「年齢オフセット例外」が含まれていないため、例外クラスをカスタマイズする必要があります.カスタム例外はいつ必要ですか???Javaで提供される例外が実際の開発ニーズを満たすことができない場合は、例外をカスタマイズする必要があります.異常クラスをカスタマイズするにはどうすればいいですか??カスタム例外クラスは例外システムに継承する必要があります.一般的には、ExceptionクラスまたはRuntimeExceptionクラスに継承すればいいです.カスタム例外の注意点1)カスタム例外は、2つの構造方法、1つはパラメトリック構造方法、もう1つは詳細な例外記述を伴う構造方法を提供する必要があります.2)カスタム例外は例外体系に継承されなければならない.例外体系に継承されたクラスだけがthrowとthrowsキーワードを使用することができる.
public class Test02 {
	public static void main(String[] args) throws AgeOutOfBoundsException {
		Student stu = new Student();
		stu.setAge(-18);
	}
}
public class Student {
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	//   :       ||      250
	public void setAge(int age) throws AgeOutOfBoundsException {
		if(age < 0 || age > 250) {
			throw new AgeOutOfBoundsException("      :" + age);
		}
		else {
			this.age = age;
		}
	}
	
}
/**
 *        
 */
public class AgeOutOfBoundsException extends Exception {
	public AgeOutOfBoundsException() {
		super();
	}
	
	public AgeOutOfBoundsException(String message) {
		super(message);
	}
}

2.異常の分類
思考:「年齢の限界異常」はExceptionとRuntimeExceptionの違いに受け継がれている??テストでは、ExceptionとRuntimeExceptionに継承される違いがあることがわかりました.これは異常分類を引き起こしました.
2.1.異常の分類
a)ランタイム異常(Runtime Exception)->ランタイムにRuntimeExceptionクラスとそのサブクラスが現れるのはランタイム異常である.特徴:コンパイル時に、プログラムに現れる異常を強制的に処理しない(処理できる、処理しない)b)コンパイル時異常(Checked Exception)->コンパイル時にExceptionクラスとそのサブクラスが現れる(実行異常クラスを含まない)はすべてコンパイル時異常に属する.特徴:コンパイル時に、プログラムに現れた異常を強制的に処理する(強制処理)
2.2.Throwable分類の補足について
a)Errorとランタイム異常は,コンパイル時に検出されないため,我々は「チェック不可異常(UnChecked Exception)」と呼ぶ.b)コンパイル時異常は,コンパイル時に検出されるので,チェック可能異常(Checked Exception)と呼ぶ.
2.3.異常処理の方式
a)異常(throws)を宣言することは,異常を消極的に処理する方法b)異常(try...catch...finally)を捕捉することであり,異常を積極的に処理する方法である.
2.4.異常の処理の宣言異常(throws)
メソッドボディに例外が発生した場合、この例外をメソッドボディで処理できない場合は、メソッドボディに発生した例外をthrowsキーを使用してメソッドに宣言し、「メソッドの呼び出し者に報告する」と、メソッドの呼び出し者に渡して処理できます.構文:[修飾子]戻り値タイプメソッド名(パラメータリスト)throws例外クラス1異常類2,異常類3,…{//メソッド体}注意事項:1)異常(throws)を宣言することは,異常を消極的に処理する方法である.メソッド体に現れる異常を我々が処理できない場合は,その異常をメソッドに宣言し,メソッドの呼び出し者に渡して解決することができる.2)メソッド体に複数の異常オブジェクトが投げ出された場合,では、メソッド宣言の上にthrowsの複数の例外クラスを宣言し、複数の例外クラスの間をカンマで分割する必要があります.
2.5.throwとthrowsの違い
位置区別throw:メソッドボディでthrows:メソッド宣言の上で、最も後ろの内容でthrowを区別します:投げたのは異常オブジェクトで、1つの異常オブジェクトしか除外できません!throws:異常クラスが宣言され、複数の異常クラスを宣言できます!本質的な違いthrow:例外オブジェクトを投げ出し、throwキーワードを実行すれば、間違いなく例外オブジェクトを投げ出す!throws:例外クラスを宣言し、宣言メソッドで例外が発生する可能性がありますが、必ずしも例外が発生するとは限りません.
class ArrayUtil {
	/**
	 *              
	 * @param arr   
	 * @param index   
	 * @return     
	 * @throws NullPointerException
	 * @throws ArrayIndexOutOfBoundsException
	 */
	public static int get(int[] arr, int index) throws NullPointerException, ArrayIndexOutOfBoundsException{
		//     1,     
		if (null == arr) {
			throw new NullPointerException("arr null");
		}
		//     2,      
		if(index < 0 || index >= arr.length) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		//       
		int value = arr[index];
		System.out.println("value:" + value);
		return value;
	}
}

public class Test02 {
	public static void main(String[] args) {
		int[] arr = {11, 22, 33};
		ArrayUtil.get(arr, 1);
		
		// int[] arr = new int[1024*1024*1024];
	}
}

3.異常処理
異常の処理方式の捕捉異常(try...catch...finally)注意:この方式は積極的な処理方式である.
3.1.try...単一catch
  	    :try {
  			//            
  		}
  		catch(      ) {
 			//  try              
      }

注意:コンソールで「スタック異常情報の印刷」を行うと、プログラムが終了するとは限りません.
public class Test01 {
	public static void main(String[] args) {
		Student stu = new Student();
		try {
			stu.setAge(-18); // throw new AgeOutOfBoundsException("      :" + age)
			System.out.println("try over ...");
		}
		catch(AgeOutOfBoundsException exception) {
			//           !
			// System.out.println("getMessage:" + exception.getMessage()); //       
			// System.out.println("toString:" + exception.toString()); //       
			exception.printStackTrace();  //             
		}
		//          ,           
		System.out.println("main over ...");
	}
}
public class Student {
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	//   :       ||      250
	public void setAge(int age) throws AgeOutOfBoundsException, NullPointerException {
		if(age < 0 || age > 250) {
			throw new AgeOutOfBoundsException("      :" + age);
		}
		else {
			throw new NullPointerException();
			// this.age = age;
		}
	}
	
}

public class ArrayUtil {
	public static int get(int[] arr, int index) throws NullPointerException, ArrayIndexOutOfBoundsException{
		//     1,     
		if (null == arr) {
			throw new NullPointerException("arr null");
		}
		//     2,      
		if(index < 0 || index >= arr.length) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		//       
		int value = arr[index];
		return value;
	}
}

3.2.义齿
1つのtryは複数のcatchに対応することができ、これにより異なる異常情報に対して正対的な処理を実現することができる.
 	      : try {
  			  //            
  		  }
 		  catch(   1    1) {
  			  //  try              
         }
         catch(   2   2) {
  			  //  try              
         }
        ....

注意事項1)複数のcatchが発生した場合は、catchが上から下へ順番に一致するため、親異常のcatchを一番後ろに置く必要があります.2)複数のcatchの場合,出現する複数の異常に対して同じ処理を行うと,catch(A r a y IndexOutOfBoundsException|Null PointerException|AgeOutOfBoundsException){}
class AAExcpetion extends Exception {}
class BBExcpetion extends AAExcpetion {}
class CCExcpetion extends BBExcpetion {}

class Demo {
	public void method(int index) throws AAExcpetion, BBExcpetion, CCExcpetion {
		if(index == 1) {
			throw new AAExcpetion();
		}
		else if(index == 2) {
			throw new BBExcpetion();
		}
		else {
			throw new CCExcpetion();
		}
	}
	
	public void start(int index) throws AgeOutOfBoundsException, NullPointerException, ArrayIndexOutOfBoundsException {
		if(index == 0) {
			throw new NullPointerException();
		}
		else if(index == 1) {
			throw new AgeOutOfBoundsException();
		}
		else {
			throw new ArrayIndexOutOfBoundsException();
		}
	}
}

public class Test02 {
	public static void main(String[] args) {
		//     ( )
		try {
			new Demo().start(0);
		} catch (ArrayIndexOutOfBoundsException | NullPointerException | AgeOutOfBoundsException e) {
			e.printStackTrace();
		}
		
		/*//     ( )
		try {
			new Demo().method(0);
		} catch (CCExcpetion e) { //    
			e.printStackTrace();
		} catch (BBExcpetion e) { //    
			e.printStackTrace();
		} catch (AAExcpetion e) { //    
			e.printStackTrace();
		}*/
		
		// try... catch  
		/*int[] arr = {11, 22, 33};	
		try {
			int value = ArrayUtil.get(null, 2); // throw new NullPointerException("arr null");
			System.out.println("value:" + value);
		}
		catch(NullPointerException e) { //                      
			e.printStackTrace();
		}
		catch (ArrayIndexOutOfBoundsException e) { //                      
			e.printStackTrace();
		}
		System.out.println("over");*/
	}
}

3.3.try…catch…finally
try {
  			//            
    	}		 
    	catch(   1   ) {
    		//  try              
    	}
    	catch(   2   ) {
    		//  try              
    	}
   	......
    	finally {
    		//   try          ,finally       
    	}

注意:1)tryまたはcatchにreturnキーワードが存在してもfinallyコードブロックのコードを実行してからメソッドを終了します.tryまたはcatchで仮想マシン(JVM)を終了する操作、すなわち「System.exit(0)」コードを実行している場合にのみ、finallyは実行されません.2)プログラムは異常が発生するかどうかにかかわらずfinallyのコードが実行されるため,一般的にfinallyでリソースを閉じる操作を実行する.3)例えば、データベースを閉じる、IOストリームを閉じるなど
public class Test03 {
	public static void main(String[] args) {
		int[] arr = {11, 22, 33};
		try {
			int value = ArrayUtil.get(null, 0);
			System.out.println(value);
			// return; //     ,            finally    , finally               
			System.exit(0); //      ,    !
		}
		catch(NullPointerException e) {
			e.printStackTrace();
			System.exit(0); //      ,    !
		}
		catch(ArrayIndexOutOfBoundsException e) {
			e.printStackTrace();
			return; //     ,            finally    , finally               
		}
		//          ,  finally     
		finally {
			System.out.println("        ,finally       ");
		}
		//      ,       
		System.out.println("over");
	}
}


3.4.try…finally
try {
 			//            
 	  	 }
    	 finally {
    		//        
   	 }

使用場面:tryで異常が発生したが,我々自身では処理できないため,この異常をメソッドに宣言し,呼び出し者に渡して処理する.tryでリソースを開く操作が実行されているため、finallyでリソースを閉じる必要があります.
3.5.異常処理のまとめについて
3.5.1异常の処理方法はどれらがありますか??
a)宣言異常(throws)、消極的な処理方式b)捕捉異常(try...catch...finally)、積極的な処理方式
3.5.2どれらの异常は私达が処理する必要がありますか??
a)コンパイル時異常,我々はコンパイル時期に処理(処理しなければならない)b)実行時異常を行わなければならない,我々はコンパイル時期に処理してもよいし,コンパイル時期に処理しなくてもよい(処理してもよいし,処理しなくてもよい)
3.5.3宣言異常(throws)???スナップ異常(try...catch...finally)???
a)プログラムに異常が発生したが,我々自身が処理できない場合,その異常をメソッドに宣言し,呼び出し者に渡して処理することができる.b)プログラムに異常が発生し,我々自身がその異常を処理できるようになった場合,その異常を上に宣言するのではなく,自発的にこの異常を解決する.e.toString():異常種別とエラー情報を取得e.getMessage():エラー情報を取得e.printStackTrace():コンソールに異常種別、エラー情報、エラー位置などを印刷する
class Test {
	public static void start(int index) throws AgeOutOfBoundsException {
		if(index == 0) {
			throw new AgeOutOfBoundsException();
		}
	}
}

public class Test04 {
	public static void main(String[] args) throws AgeOutOfBoundsException 
		int[] arr = {11, 22, 33};
		try {
			//              ,            ,           ,
			//                 ,       finally        !
			Test.start(0);
		}
		finally {
			System.out.println("        ,finally       ");
		}
		//      ,       
		System.out.println("over");
	}
}