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");
}
}
}