java异常菜鸟教程,java异常详解
什么是异常现象?异常处理异常抛出处理异常抛出声明异常最终捕获异常:异常处理过程自定义异常
00-1010异常在我们写代码的时候是很常见的,因为程序员大部分时间都在修复bug。在java中,通过throwable顶级类可以分为两类,一类是Error,一类是Exception。
Error(错误):错误不同于异常,错误是无法处理的,而是程序员造成的问题,比如语法错误,所以程序员要检查自己的语法,比如结果错误(StackOverflowError和OutOfMemoryError)
),那就需要程序员自己检查逻辑了。
Exception(异常):这个可以用一些方法处理,比如throws(声明异常)和try{}catch{}(处理异常)我们后面会讲到。以上就是我们处理异常的所有方式,异常分为检查型异常(编译期异常)和非检查型异常(RuntimeException)。
编译时异常:程序无法编译,即编译时异常。例如,克隆时必须通过抛出来声明异常。
运行时异常(Runtime exception):表示程序可以编译,但在运行时出现异常。例如:NullPointerException,
ArrayIndexOutOfBoundsException、ArithmeticException .
我们可以处理上述所有异常,但是错误需要程序员自己检查代码。
00-1010我们有两种处理方式:
一个是预先防御:
布尔ret=falseRet=登录游戏();如果(!ret){处理登录游戏错误;返回;} ret=开始匹配();如果(!ret){处理匹配错误;返回;} ret=游戏确认();如果(!ret){处理游戏确认错误;返回;} ret=选择英雄();如果(!ret){处理英雄选择错误;返回;} ret=加载游戏画面();如果(!ret){处理加载游戏错误;返回;} .
事先防御型是检查每一步是否有错误,缺点是代码非常混乱,效率很低;
一是事后承认错误:
试试{登录游戏();开始匹配();游戏确认();选择英雄();加载游戏画面();} catch(登录游戏异常){处理登录游戏异常;} catch(开始匹配异常){处理开始匹配异常;} catch(游戏确认异常){处理游戏确认异常;} catch(英雄选择异常){处理英雄选择异常;} catch(游戏画面异常加载){处理游戏画面异常加载;} .
这种方法是将代码中所有可能的异常都放在try中。如果捕捉到异常,这种方法是先操作,处理遇到的问题。
我们经常使用第二个trycatch来使代码简洁、清晰、高效。
00-1010如果哪个代码不符合你的预期,我们会在这个代码中抛出一个异常。在java中,我们通过关键字throw抛出一个异常。
这是语法throw new exception(您想要抛出的异常)
class test demo { public static void func(int a){ if(a==10){ throw new runtime exception( a==10不按预期,抛出此异常);} } public static void main(String[]args){ func(10);}}}看这段代码:比如我们的数字10不符合我们程序的预期,那么要抛出异常,我们可以这样跑出来:抛出新的运行时异常( a==10不符合预期,抛出这个异常);
00-1010我们通常有两种方法来处理异常。一种是通过throws声明异常,另一种是通过try{}catch{}检查代码块中是否有异常。如果有异常,就捕捉它们,如果没有异常,下面的代码就正常了。
00-1010语法:抛出异常,异常,异常.(可以声明多个异常)
公共类TestDemo {公共静态void函数(int[] arr
ay) { System.out.println(array[100]); } public static void main(String[] args) { int[] array = {7, 8, 9, 5, 6}; function(array); }}大家都知道这里访问100下标是数组越界异常:
接下来通过throws来声明异常:
还是会报错。
当我们也给主函数声明异常:
答案依然会报错。
所以从这里我们得出了一个结论:通过throws只是告诉编译器,这个方法可能会发生这个异常,只是声明,但是并没有进行处理异常。我们还可以发现,如果某一个方法出现了异常,那就会看这个方法有没有处理异常,如果没有处理就去看一看上层调用者有没有处理异常。这里就是func只是声明了异常,并没有进行处理异常,然后去上层调用者有没有处理异常(也就是main方法)还是没有处理异常,最后就交给JVM来处理进行终止程序。声明的异常必须是 Exception 或者 Exception 的子类。
那怎么进行处理异常呢?? 那就要通过我们接下来讲解的try{}catch来进行处理异常。
捕获异常
try{
}catch(){
}
在Java我们利用try{}catch{}来处理异常;
语法:
try{ //可能发生异常的代码 }catch(异常 变量){//例如:ArrayIndexOutOfBoundsException(要捕获的异常) e(变量) //如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时, //或者是try中抛出异常的基类时,就会被捕获到 // 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码 }finally{ //此处代码一定会执行,用于资源清理扫尾等工作 }
我们先来讲一下try{}catch(){}
/*在方法中处理异常*/public class TestDemo { public static void function(int[] array) throws ArrayIndexOutOfBoundsException { try{ System.out.println(array[100]); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("array[100]->数组下标越界异常catch->捕获成功"); } } public static void main(String[] args) throws ArrayIndexOutOfBoundsException { int[] array = {7, 8, 9, 5, 6}; function(array); }}/*在main方法中处理异常*/public class TestDemo { public static void function(int[] array) throws ArrayIndexOutOfBoundsException { System.out.println(array[100]); } public static void main(String[] args) throws ArrayIndexOutOfBoundsException { int[] array = {7, 8, 9, 5, 6}; try{ function(array); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("array[100]->数组下标越界异常catch->捕获成功"); } }}
我们使用try{}catch(){}就可以对异常进行处理,既可以在方法中处理异常也可以在main方法中处理异常,同时这里throws虽然没有什么用处,但是可以清晰的告诉程序员,这个方法未来可能会发生这个异常,所以还是有必要的。
try{}catch{}注意点 一:
当捕获异常成功的时候,后面的业务代码正常执行,如果没有捕获那就不会执行。
try{}catch{}注意点 二:
当try里检查到异常,catch就会捕获,计算这个异常后面还有异常也不会执行。
try{}catch{}注意点三:
throws只是声明异常,并没有处理异常,我们要通过try{}catch(){}来处理异常。
try{}catch{}注意点四:
当catch捕获的异常类型与发生异常类型不符合,就不会被捕获,就继续往外抛异常知道JVM收到后终止程序
try{}catch{}注意点五:
当发生多种异常的时候,那就要多种catch来捕获,多种异常,多次捕获。
try{}catch{}注意点六:
Exception是所有类的父类不能在前面捕获,而是应该放在最末尾进行收尾工作。
既然Exception类是所对应异常类的父类,那可不可以捕获Exception,即多次异常,一次捕获呢??
catch 进行类型匹配的时候, 不光会匹配相同类型的异常对象, 也会捕捉目标异常类型的子类对象
答案是不建议的。因为当代码进行复杂的时候,只捕获Exception类并不知道究竟是什么处理出了问题。
打印异常信息
我们还可以利用printStackTrace来打印错误信息。
finally:
finally经常与try{}catch(){}进行一起使用,finally主要是进行资源的清理,的扫尾工作,且finally一定会被执行。
我们来看这样一段代码结果会是什么??
public class TestDemo { public static int function(int[] array) throws ArrayIndexOutOfBoundsException { try { System.out.println(array[100]); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("array[100]->数组下标越界异常catch->捕获成功"); return -1; }finally{ System.out.println("finally主要进行资源回收和清理的扫尾工作~~~"); return 9; } } public static void main(String[] args) throws ArrayIndexOutOfBoundsException,ArithmeticException { int[] array = {7, 8, 9, 5, 6}; System.out.println(function(array)); System.out.println("以下是业务代码~~~~~~"); }}
答案并不是我们想的return-1,执行结束,而是return9,我们这里可以理解为finally的9将catch里的-1覆盖。所以finally里面的代码是一定会执行的。
异常的处理流程
我的理解:
第一步检查try里面的代码里是否有异常,如果有异常catch就进行捕获,如果没有异常接着往下执行,这里catch如果没有捕获到就看一看上层调用者有没有处理,有处理就进行处理,没有处理就交给JVM终止程序。如果catch捕获到了,下面正常的业务代码正常执行。最后无论catch是否捕获到了异常,finally里面的代码都会执行。
官方:
程序先执行 try 中的代码如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.如果找到匹配的异常类型, 就会执行 catch 中的代码如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).如果上层调用者也没有处理的了异常, 就继续向上传递.一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止。
自定义异常
在我们做很大型的项目的时候,我们就会发现,我们遇到的异常,在Java中的内置异常并没有,所以我们就需要自己定义一个异常,来维护我们实际中遇到的异常。
java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时需要维护符合我们实际情况的异常结构
在Java中自己声明异常,不是说你写了个异常的名字就是一个异常,而是在你自己定义的异常需要取继承原有的内置异常。
我们通过一个登陆的代码来讲解自定义异常:
class LogIn { private String name ="Admin";//用户名 private String password= "CsDn1263987..0"; public void logInFor(String name,String password) throws UserNameErrorExecption, PasswordErrorException { if(!this.name.equals(name)){ throw new UserNameErrorExecption("用户名参数异常!!!"); } if(!this.password.equals(password)) { throw new PasswordErrorException("用户密码参数异常!!!"); } System.out.println("~~~登陆成功~~~"); }}public class TestDemo{ public static void main(String[] args) throws UserNameErrorExecption, PasswordErrorException { LogIn logIn = new LogIn(); //logIn.logInFor("Admin","CsDn1263987..0"); try{ logIn.logInFor("Admin","CsDn126398..0"); }catch(UserNameErrorExecption nameError) { nameError.printStackTrace(); System.out.println("用户名错误!!!"); }catch(PasswordErrorException passwordError) { passwordError.printStackTrace(); System.out.println("密码错误!!!"); } }}
自定义异常:
class PasswordError extends Exception { public PasswordError(String message) { super(message); }}
class UserNameError extends Exception { public UserNameError(String message) { super(message); }}
这就是我们定义的两个异常。
通过继承Exception来定义两个异常。
一般我们自定义异常要继承Exception或者是RunTimeException,定义其他的也可以。
自定义异常通常会继承自 Exception 或者 RuntimeException继承自 Exception 的异常默认是受查异常继承自 RuntimeException 的异常默认是非受查异常到此这篇关于Java零基础讲解异常的文章就介绍到这了,更多相关Java异常内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。