java将所有的错误封装成为一个对象,其根本父类为Throwable

Throwable
 --Error:指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,
   因为已经失去了运行所必须的物理环境,一般不编译特定的代码进行处理
 --Exception:要用针对性的处理方式进行处理
  --RunntimeException:运行时异常,可以不进行处理
       这类异常可以不捕获或声明,编译可以通过
  --非RunntimeException:要进行处理,这类异常要捕获或是声明,不然编译无法通过
 
 常用方法:
  getMessage():获取异常信息,返回字符串
  toString():获取异常类名和异常信息,返回字符串
  printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置
  printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅

1.异常的处理方式:
 第一种方式:捕获
  (1).后面可以跟多个catch异常对象,但异常对象应该按由子类到父类的方式排列
   如果父类异常排在子类的前面,那么后面的子类异常会执行不到
   
 

try{
   可能出现异常的代码
  }catch(异常类型,变量){
   异常处理方式
  }


  
  (2).finally是一定会执行的语句,一般用来关闭资源
  

try{
   可能出现异常的代码
  }catch(异常类型,变量){
   异常处理方式
  }finally{
   一定会执行的语句
  }


  
  (3).其实这种方式并不能捕获异常,因为没有catch进行处理,当try中出现异常时,程序还是
   会直接抛出异常给上级(指的是运行时异常,非运行时异常编译不通过)
  

try{
   可能会出现异常的代码
  }finally{
   一定会执行的语句
  }


 
 第二种方式:声明
  在函数内部直接将异常抛出,并在函数上声明这个异常,将异常交由上一级处理
  
  throw与throws区别
  throw:用在函数内部,在函数内部抛出异常,后面跟的是异常对象
  throws:用在函数上,后面跟的是异常类,并且可以跟多个异常类,中间有逗号分开

//第一种方式:捕获异常
public class ExceptionTest{
	public static void main(String[] args){
		div(4,7);
		System.out.println("main code");
	}
	
	public static void div(int a,int b){
		//捕获异常,当出现异常时,语句直接跳转到catch中进行异常的处理,try中出现异常的后面的语句就不会执行了
		try{
				int temp=a/b;
				int[] num=new int[a];
				System.out.println("temp="+temp);
				System.out.println(num[a]);
			}catch(ArithmeticException e){
				e.printStackTrace();
				//try后可以跟多个catch,应按照子类到父类的排列顺序,
				//如果try中出现了catch中所有的异常,那么程序会直接抛出异常给上一级
				//catch语句中不能再嵌套try--catch
			}catch(ArrayIndexOutOfBoundsException e){
				e.printStackTrace();
				//finally中执行的一般是关闭资源的操作
			}finally{
				System.out.println("一定会执行的语句");
			}
	}
}

//第二种方式:声明异常
public class ExceptionTest{
	public static void main(String[] args) throws Exception{
		//调用者可以进行try或在函数上声明,如果进行了try那后面的语句还会执行,只是声明那后面的语句就不会执行了
		div(4,0);
		System.out.println("main code");
	}
	//在函数上声明异常,将异常交由上一级处理
	public static void div(int a,int b) throws Exception{
		int temp=a/b;
		System.out.println("temp="+temp);
	}
}

2.自定义异常类:必须是自定义类继承Exception类体系
     因为异常类和异常对象都要具有可抛性,这个可抛性是Throwable这个体系中独有特点,所有自定义异常类要继承于
     这个体系,也只有这个体系中的类才可以被throw和throws所操作

 

//如果不想对自定义的异常类进行处理,可以让自定义类继承RuntimeException
class MyException extends Exception {
		MyException(String message){
		super(message);
	}
}
public class ExceptionTest{
	public static void main(String[] args) throws MyException{
		show(-1);
	}
	public static void show(int a) throws MyException{
		if(a<0)
		//抛出自定义异常类
			throw new MyException("角标为负数");
		int[] num=new int[a];
		System.out.println("num="+num[a]);
	}
}

3.异常类在子父类中的体现:
 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
 如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
 如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,如果子类发生了异常,只能进行try

 

class MyException extends Exception {
		MyException(String message){
		super(message);
	}
}
class Father{
	String str="lidaofu";
	char[] name=str.toCharArray();
	//父类抛出的异常
	public void show(int index) throws ArrayIndexOutOfBoundsException{
		System.out.println("name["+index+"]"+name[index]);
	}
}
class Son extends Father{
	int age=0;
	//当子类继承父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
	//如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,只能通过try--catch解决
	public void show(int index) throws ArrayIndexOutOfBoundsException{
		System.out.println("name["+index+"]="+name[index]);
		try{
			if(age==0){
				throw new MyException("除数为零啦");
				//当throw单独存在时,后面不能跟语句,因为执行不到
				//System.out.println(age);编译失败,这句话是执行不到的
				}
			int temp=index/age;
			System.out.println("temp="+temp);
		}catch(MyException e){
			e.printStackTrace();
		}
	}
}
public class ExceptionTest{
	public static void main(String[] args) throws MyException{
		Son s=new Son();
		s.show(3);
		System.out.println("main code");
	}	
}

4.finally的执行时间问题
  finally语句是在return语句之后,跳转到上一级程序之前执行(即return语句中间执行)
  finally中的语句一定会执行,是建立在对应的try得到执行情况下,如果程序在try语句之前就发生了
  异常或就已经结束,那finally中的语句是不会执行的
  finally在一种情况下不会执行,System.exit(0):程序停止运行,退出虚拟机

 

public class ExceptionTest{
	public static void main(String[] args){
		System.out.println(test());
	}
	public static String test(){  
     try{  
			System.out .println("try block");  
			return test1 ();  
		} finally {  
			System.out .println("finally block");
			//return "finally"; 如果finally中有返回值,那么finally返回值就会替换掉上一级方法中的返回值
			//					这一句如果执行,那程序上一级方法中的after return 就会被finally所替换
		}  
	}  
	public static String test1(){  
		System.out.println("return statement");  
		return "after return";  
	}
}

 程序结果为:
  try block
  return statement
  finally block
  after return
 
 原因分析:
   1.try语句块,return test1(),则调用test1方法
   2.test1()执行后返回"after return",返回值"after return"保存在一个临时区域里
   3.执行finally语句块。若finally语句有返回值,则此返回值将替换掉临时区域的返回值
   4.将临时区域的返回值送到上一级方法中。

 

public class ExceptionTest{
	public static void main(String[] args){
		int a=5;
		int[] arr=new int[5];
		//return 0;要想让方法停止运行可以return或throw个异常
		int i=a/0;
		try{
			System.out.println(arr[6]);
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.getMessage());
			System.out.println("角标越界");
		//这里的finally语句是不会执行的,因为在try语句之前程序就已经停止运行了
		}finally{
			System.out.println("finally");
		}
	}
}