荷泽网站建设,哈尔滨免费建站模板,旅游网页首页,义乌网站搭建文章目录一、异常的概念二、异常的分类1.常见的几个运行时异常2.常见的几个编译时异常三、处理异常1.防御式编程2.异常的抛出3.异常的捕获#xff08;1#xff09;异常声明throws#xff08;2#xff09;try-catch捕获并处理4.异常的处理流程5.自定义异常一、异常的概念
异…文章目录一、异常的概念二、异常的分类1.常见的几个运行时异常2.常见的几个编译时异常三、处理异常1.防御式编程2.异常的抛出3.异常的捕获1异常声明throws2try-catch捕获并处理4.异常的处理流程5.自定义异常一、异常的概念异常Exception是指程序在运行过程中出现的错误情况这些错误可能导致程序的正常流程中断。异常可以是由程序自身的逻辑错误引起也可以是由外部因素如文件未找到、网络中断等导致。二、异常的分类Error错误**描述**错误通常指的是由Java虚拟机JVM自身引起的严重问题这些问题往往超出了程序的控制。错误通常无法通过程序代码来恢复因此是不建议进行捕获和处理的虽然它们可以写在 catch 后的括号中。**示例**常见的错误有 OutOfMemoryError内存不足、StackOverflowError栈溢出和 NoClassDefFoundError类定义未找到。**处理建议**对于错误通常不需要程序员处理发生后程序很可能会直接终止。正确的做法是优化代码以避免这些错误的发生。Exception异常**描述**异常是程序运行过程中可以被捕获并处理的问题。当程序遇到异常时可以通过适当的处理机制如 try-catch 块来防止程序崩溃。分类一检查型异常Checked Exceptions又名编译时异常/受查异常描述检查型异常是在编译时被检查的异常。程序员必须在代码中进行处理否则编译器会报错。它们通常表示外部环境的问题如文件未找到、网络连接失败等。**示例**IOException输入输出异常、SQLExceptionSQL异常、 ClassNotFoundException类未找到异常CloneNotSupportedException克隆异常。处理方式使用 try-catch 块捕获异常或在方法签名中使用 throws 声明该异常。二非检查型异常Unchecked Exceptions又名运行时异常描述非检查型异常是在运行时发生的异常它们通常是由程序的逻辑错误引起的如数组越界、空指针引用等。编译器不会强制要求程序员处理这些异常。**示例**NullPointerException空指针异常、ArrayIndexOutOfBoundsException数组下标越界、IllegalArgumentException非法参数异常。处理方式虽然不强制要求捕获但建议在适当的地方进行处理以提高程序的健壮性。异常其实就是一个一个的类所有的异常都继承于顶级父类Throwable1.常见的几个运行时异常1NullPointerExceptionNullPointerException 空指针异常当应用程序试图使用null作为对象的引用时会抛出NullPointerException。这通常发生在尝试访问对象的方法或属性时。publicclassExample{publicstaticvoidmain(String[]args){Stringstrnull;System.out.println(str.length());// 尝试使用空引用}}2ArithmeticExceptionArithmeticException 数学运算异常算数异常当发生算术运算的异常情况时会抛出ArithmeticException。最常见的情况是除以零。例如publicclassExample{publicstaticvoidmain(String[]args){intresult10/0;}}3ArrayIndexOutOfBoundsExceptionArrayIndexOutOfBoundsException 数组下标越界异常当尝试访问数组中不存在的索引时会抛出 ArrayIndexOutOfBoundsException。该异常表示访问的索引超出了合法范围0到数组长度-1。publicclassExample{publicstaticvoidmain(String[]args){int[]arrnewint[5];System.out.println(arr[-1]);}}4ClassCastExceptionClassCastException 类型转换异常当尝试将对象强制转换为不兼容的类型时会抛出ClassCastException。这通常发生在使用类型转换时。publicclassExample{publicstaticvoidmain(String[]args){ObjectobjnewString();Integernum(Integer)obj;}}5NumberFormatExceptionNumberFormatException 数字格式不正确异常当尝试将字符串转换为数字格式时如果字符串的格式不符合数字的要求就会抛出 NumberFormatException。例如尝试将一个非数字字符串转换为整数。例如publicclassExample{publicstaticvoidmain(String[]args){Stringstrabc;intnumInteger.parseInt(str);}}2.常见的几个编译时异常1、SQLExceptionSQLException 是在与数据库交互时可能发生的异常。它可以指示由于数据库访问错误或其他数据库问题如查询语法错误、连接失败等而导致的错误。2、IOExceptionIOException 是与输入/输出操作相关的异常例如文件读取或网络通信时出错。它是处理文件和流操作时的常见异常。3、FileNotFoundExceptionFileNotFoundException 是 IOException 的一个子类在尝试打开一个不存在的文件时抛出。它通常在文件操作时进行检查。4、ClassNotFoundExceptionClassNotFoundException 是当应用程序尝试通过字符串名称加载类但没有找到对应类时抛出的异常。这通常发生在使用反射或动态加载类时。5、EOFExceptionEOFException 是在读取文件时遇到文件末尾End of File而未能成功读取数据时抛出的异常。通常在使用数据输入流DataInputStream时会遇到此异常。6、CloneNotSupportedException一个类想要调用Object类的clone()方法实现克隆但没有实现Cloneable接口Cloneable是一个标记接口没有任何方法仅用于标识该类支持克隆。三、处理异常1.防御式编程错误在代码中是客观存在的. 因此我们要让程序出现问题的时候及时了解到我们是哪里出现了错误因此我们得到了两个得到错误位置的方式。1事前防御型LBYL这种方式我们其实会发现一些缺陷我们的正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱。2事后认错型EAFP当然对于事后认错型我们发现我们的代码中使用了两个关键字try和catch.然而对于事后认错型我们有五个主要的关键字throw、try、catch、final、throws。2.异常的抛出语法thrownewXXXException(异常产生的原因);注意throw必须写在方法体内部抛出的对象必须是Exception 或者 Exception 的子类对象如果抛出的是 RunTimeException 或者 RunTimeException 的子类则可以不用处理直接交给JVM来处理如果抛出的是编译时异常用户必须处理否则无法通过编译异常一旦抛出其后的代码就不会执行3.异常的捕获既然我们已经得到了信息接下来就是要捕获并处理他而异常的捕获也就是异常的具体处理方式主要有两种异常声明throws 以及 try-catch捕获处理。1异常声明throws处在方法声明时参数列表之后当方法中抛出编译时异常用户不想处理该异常此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常提醒方法的调用者处理异常。语法:修饰符 返回值类型 方法名(参数列表) throws 异常类型1异常类型2…{}而我们知道了异常的声明方式我们就可以成功的解决这个问题了注意事项1、throws必须跟在方法的参数列表之后2、声明的异常必须是 Exception 或者 Exception 的子类3、调用声明抛出异常的方法时调用者必须对该异常进行处理或者继续使用throws抛出4、方法内部如果抛出了多个异常throws之后必须跟多个异常类型之间用逗号隔开如果抛出多个异常类型 具有父子关系直接声明父类即可。多个异常类型具有父子关系我们要注意如果多种类型具有父子类关系再次抛出只需要声明父类2try-catch捕获并处理throws对异常并没有真正处理而是将异常报告给抛出异常方法的调用者由调用者处理。如果真正要对异常进行处理就需要try-catch。语法try{// 将可能出现异常的代码放在这里}catch(要捕获的异常类型 e){// 如果try中的代码抛出异常了此处catch捕获时异常类型与try中抛出的异常类型一致时 或者是try中抛出异常的基类 时就会被捕获到// 对异常就可以正常处理处理完成后跳出try-catch结构继续执行后序代码}catch(要捕获的异常类型 e){// 对异常进行处理}finally{// 此处代码一定会被执行到}// 后序代码// 当异常被捕获到时异常就被处理了这里的后序代码一定会执行// 如果捕获了由于捕获时类型不对那就没有捕获到这里的代码就不会被执这就是我们对异常的处理但是我们发现原本编译器其实会告诉我们异常的信息当现在我们并不知道异常是什么那么我们该怎样得到异常信息呢其实很简单只需要我们在catch处加上异常信息的打印即可。当然由于异常的种类有很多, 因此我们要根据不同的业务场景来决定我们是否使用异常处理对于比较严重的问题(例如和算钱相关的场景), 应该让程序直接崩溃, 防止造成更严重的后果对于不太严重的问题(大多数场景), 可以记录错误日志, 并通过监控报警程序及时通知程序猿对于可能会恢复的问题(和网络相关的场景), 可以尝试进行重试1、try-catch 语句try-catch语句用于捕捉和处理在try块中可能出现的异常。其基本语法结构如下try{// 可能抛出异常的代码}catch(ExceptionTypee){// 异常处理代码}例如try{intresult10/0;// 可能抛出 ArithmeticException}catch(ArithmeticExceptione){System.out.println(ArithmeticException: e.getMessage());}注意 1. try块内抛出异常位置之后的代码将不会被执行2. 如果抛出异常类型与catch时异常类型不匹配即异常不会被成功捕获也就不会被处理继续往外抛直到JVM收到后中断程序----异常是按照类型来捕获的2、try-catch-finally 语句在写程序时有些特定的代码不论程序是否发生异常都需要执行比如程序中打开的资源网络连接、数据库连接、IO流等在程序正常或者异常退出时必须要对资源进行回收。另外因为异常会引发程序的跳转可能导致有些语句执行不到finally就是用来解决这个问题的。语法try{// 可能会发生异常的代码}catch(异常类型 e){// 对捕获到的异常进行处理}finally{// 此处的语句无论是否发生异常都会被执行到}// 如果没有抛出异常或者异常被捕获处理了这里的代码也会执行try{// 可能抛出异常的代码}catch(ExceptionTypee){// 异常处理代码}finally{// 无论是否发生异常都会执行的代码}3、多个 catch 结构1介绍多个catch结构用于处理try块中可能抛出的不同类型的异常。当一个try块中的代码可能抛出多种异常时可以使用多个catch块来分别捕获和处理这些异常。这样可以提高程序的健壮性和可维护性。多个catch结构的基本语法如下try{// 可能抛出异常的代码}catch(ExceptionType1e1){// 处理 ExceptionType1 异常}catch(ExceptionType2e2){// 处理 ExceptionType2 异常}catch(ExceptionType3e3){// 处理 ExceptionType3 异常}// 可选的 finally 块finally{// 清理操作无论是否发生异常都会执行}但是注意我们是不能够捕获到多个异常的需要注意的是在多个catch块中子类异常必须放在父类异常之前。例如如果同时有IOException和Exception则IOException应该放在前面。否则Exception会捕获所有异常导致子类IOException的catch块无法被执行。可以使用一个通用的异常捕获块如Exception来捕获所有未被具体捕获的异常通常放在最后的 catch 语句块中。如果异常之间具有父子关系一定是子类异常在前catch父类异常在后catch否则语法错误我们知道NullPointerException是Exception的子类所以当为空指针异常时我们可以写成这样但是如果我们想要这两异常都存在我们一定要让子类异常在前catch父类异常在后catch可以通过一个catch捕获所有的异常即多个异常一次捕获(不推荐)当然对于上述这种方式我们是不推荐的4、一个 catch 块捕获多个异常如果多个异常的处理方式是完全相同, 对于这个代码我们是可以进行简化的但是我们并不是很建议这样来写因为我们并不能明确的知道到底是什么导致的异常从Java 7开始可以在一个catch块中捕获多个异常使用管道符号**|**分隔多个异常类型。这对于处理多个异常类型时执行相同的处理逻辑非常有用。try{// 可能抛出异常的代码}catch(IOException|NullPointerExceptione){// 处理 IOException 或 NullPointerExceptionSystem.out.println(Exception: e.getMessage());}5、try-finally 语句这种方式只使用了 try 和 finally 块没有 catch 块用来捕获和处理异常。这通常用于清理资源例如关闭文件、数据库连接等。try{// 可能抛出异常的代码}finally{// 无论是否发生异常都会执行的代码}但是我们发现 finally 和 try-catch-finally 后的代码都会执行那为什么还要有finally呢这种写可以确保如果异常发生可以执行 finally 语句块中的语句执行完 finally 块中的语句后程序就因异常结束了后面的外部语句就不会被执行了。例如publicclassExample{publicstaticvoidmain(String[]args){try{intres1/0;}finally{System.out.println(finally 语句块);}System.out.println(外部语句);}}运行结果可以看到因为异常没有被捕获所以只执行了 finally 语句块后程序就因为异常而崩溃了。6、补充1可能出现异常的语句要放到 try 块中只有放到 try 语句块中的代码抛出的异常才能被 catch 语句块捕获到。publicclassExample{publicstaticvoidmain(String[]args){intres2/0;// 这里抛出的异常不会被捕获try{}catch(ArithmeticExceptione){System.out.println(e.getMessage());}}}这样直接执行的结果是程序结束异常没有被捕获2catch 捕获异常后就会跳入到 catch 块中执行在 try 块中的某一句代码抛出异常后该异常被 catch 捕获则会直接跳入 catch 语句块中执行。try 块的剩余语句不会再执行了。publicclassExample{publicstaticvoidmain(String[]args){try{intres1/0;System.out.println(...);// 这一句不会执行}catch(ArithmeticExceptione){System.out.println(e.getMessage());}}}可以发现 try 块中剩余的语句没有被执行。3catch 不会被执行的情况没有发生异常或者没有捕获到异常catch 块都不会被执行。publicclassExample{publicstaticvoidmain(String[]args){try{Stringstr1;intnumInteger.parseInt(str);System.out.println(num);}catch(NumberFormatExceptione){System.out.println(异常发生e.getMessage());}}}可以看到异常没有发生则 catch 块中的语句没有被执行。4finally 语句块无论是否有异常都会被执行finally 语句块中的代码无论是否发生异常都会执行通常用于清理资源如关闭文件或数据库连接。importjava.util.Scanner;publicclassExample{publicstaticvoidmain(String[]args){ScannerinputnewScanner(System.in);Stringstrinput.next();try{intnumInteger.parseInt(str);System.out.println(num);}catch(NumberFormatExceptione){System.out.println(异常发生e.getMessage());}finally{System.out.println(finally 代码块...);}}}可以看到无论是否发生异常finally 代码块都会执行。5与 finally 块有关的题目由于 finally 块无论是否发生异常都须被执行。publicclassExample{publicstaticintmethod(){try{Stringnamenull;name.length();}catch(NullPointerExceptione){return1;}finally{return2;}}publicstaticvoidmain(String[]args){System.out.println(method());}}运行结果2由于 finally 块无论是否发生异常都会被执行所以在 catch 块中不会返回到了 finally 块中才会返回所以最终 method() 方法返回值为 2。4.异常的处理流程如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递最后就会交给JVM导致程序终止。总结程序先执行 try 中的代码如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.如果找到匹配的异常类型, 就会执行 catch 中的代码如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).如果上层调用者也没有处理的了异常, 就继续向上传递.一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.受查异常必须处理在main里面调用function如果throws声明了异常先thorw抛出异常用catch捕获异常那就得在main里用try-catch处理这个异常不处理得话也可以在main后面跟一个一样的声明这样的话就交给了jvm处理交给jvm直接中止程序抛出了异常才会捕获到即只有try里调用方法的时候thorw抛出异常的时候才会进入catch捕获异常catch的参数列表是抛出的异常那个类的对象通过–变量.printStackTrace()打印错误信息5.自定义异常Java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常此时就需要维护符合我们实际情况的异常结构.在 Java 中定义一个自定义异常Custom Exception的本质就是定义一个类。但是这个类必须遵循一个关键的继承规则自定义异常可以继承两个主要基类之一是否可以声明当然非受查异常也是可以声明的所以我们一般在写代码的时候尽量写声明这样能有效知道我们都有那些异常类型注意继承java.lang.Exception创建的是受检查异常Checked Exception。用于表示程序可以预料和恢复的业务错误例如文件不存在、网络连接超时、账户余额不足。继承java.lang.RuntimeException创建的是不受检查异常Unchecked Exception。用于表示程序逻辑错误或不可恢复的错误例如参数无效、索引越界。不能任何异常都用一个Exception解决一开始就被Exception捕获了后面就没意义了不是所有异常都必须手动捕获。只有受检查异常Checked Exceptions必须手动处理或声明抛出而不受检查异常Unchecked Exceptions可以选择性地处理只有受检查异常要求您进行手动捕获try-catch或声明抛出throws。不受检查异常RuntimeException及其子类不需要强制手动捕获。