您的位置:首页 > 文旅 > 美景 > 营销型网站的概念_新浪重庆_合肥网站排名_推广网络营销外包公司

营销型网站的概念_新浪重庆_合肥网站排名_推广网络营销外包公司

2024/12/28 12:23:03 来源:https://blog.csdn.net/2302_80250536/article/details/144373117  浏览:    关键词:营销型网站的概念_新浪重庆_合肥网站排名_推广网络营销外包公司
营销型网站的概念_新浪重庆_合肥网站排名_推广网络营销外包公司
Java 中,将程序执行过程中发生的不正常行为称为异常

异常的体系结构

1. Throwable 是异常体系的顶层类,其派生出两个重要的子类 , Error(错误)  Exception(异常)
2. Error 指的是 Java 虚拟机无法解决的严重问题,比如: JVM 的内部错误、资源耗尽等 ,典型代表: StackOverflowError OutOfMemoryError ,一旦发生回力乏术。
3. Exception 异常产生后程序员可以通过代码进行处理,使程序继续执行。

异常的分类

1. 编译时异常
在程序编译期间发生的异常,称为编译时异常,也称为受检查异常(Checked Exception)
2. 运行时异常
在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常(Unchecked Exception)
RunTimeException以及其子类对应的异常,都称为运行时异常。
运行时指的是程序已经编译通过得到 class 文件了 , 再由 JVM 执行过程中出现的错误 .
1. 算术异常
System.out.println(10/0);
2. 数组越界异常
        int[] arr = new int[10];System.out.println(arr[20]);
3. 空指针异常
        int[] arr = null;System.out.println(arr.length);

异常的处理

防御式编程

1. LBYL : Look Before You Leap. 在操作之前就做充分的检查 . 即: 事前防御型
2. EAFP : It's Easier to Ask Forgiveness than Permission. " 事后获取原谅比事前获取许可更容易 ". 也就是先操 作, 遇到问题再处理 . 即: 事后认错型
优势:正常流程和错误流程是分离开的 , 程序员更关注正常流程,代码更清晰,容易理解代码。
异常处理的核心思想就是 EAFP
Java 中, 异常处理主要的 5 个关键字: throw try catch final throws

1. 异常的抛出

在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者,比如:参数检测。
Java 中,可以借助 throw 关键字,抛出一个指定的异常对象,将错误信息告知给调用者。具体语法如下:
public class Test {public static void main(String[] args) {       int[] arr = null;if(null==arr){System.out.println("可以执行语句");throw new NullPointerException("空指针异常");//throw 中断了执行流//throw 中断了执行流,导致这一行永远不会被执行。//System.out.println("不可达语句");//编译器会报错:unreachable statement}//如果没有抛出异常或异常被捕获处理,那么执行流会到达这一行并打印。//如果异常未处理,则程序在抛出异常后终止,这一行也不会被执行System.out.println("不执行语句");}
}

注意事项
1. throw 必须写在方法体内部
2. 抛出的对象必须是 Exception 或者 Exception 的子类对象
3. 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给 JVM 来处理
4. 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
5. 异常一旦抛出,其后的代码就不会执行

异常的捕获

异常的捕获,也就是异常的具体处理方式,主要有两种:异常声明throws 以及 try-catch捕获处理

2. 异常声明throws

处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助 throws 将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常
语法格式:
修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2...{}public void methodName() throws ExceptionType1, ExceptionType2 {// 方法实现
}
注意事项
1. throws 必须跟在方法的参数列表之后
2. 声明的异常必须是受检异常即编译时异常
3. 方法内部如果抛出了多个异常, throws 之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可。
4. 调用声明抛出异常的方法时,方法的调用者需要负责处理这些异常(通过 try-catch 或继续声明 throws

3. try-catch捕获并处理

throws 对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch
关于异常的处理方式
异常的种类有很多 , 我们要根据不同的业务场景来决定 .
对于比较严重的问题 ( 例如和算钱相关的场景 ), 应该让程序直接崩溃 , 防止造成更严重的后果
对于不太严重的问题 ( 大多数场景 ), 可以记录错误日志 , 并通过监控报警程序及时通知程序猿
对于可能会恢复的问题 ( 和网络相关的场景 ), 可以尝试进行重试 .
在我们当前的代码中采取的是经过简化的第二种方式 . 我们记录的错误日志是出现异常的方法调用信息 , 能很
快速的让我们找到出现异常的位置 . 以后在实际工作中我们会采取更完备的方式来记录异常信息
注意事项
1. try 块内抛出异常位置之后的代码将不会被执行
2. 如果抛出异常类型与 catch 时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序 ---- 异常是按照类型来捕获的
3. try中可能会抛出多个不同的异常对象,则必须用多个 catch 来捕获 ---- 即多种异常,多次捕获
如果异常之间具有父子关系,一定是子类异常在前 catch ,父类异常在后 catch ,否则语法错误
如果多个异常的处理方式是完全相同 ,中间可以用 | 隔开
可以通过一个 catch 捕获所有的异常,即多个异常,一次捕获 ( 不推荐 )
由于 Exception 类是所有异常类的父类 . 因此可以用这个类型表示捕捉所有异常 . 即: catch 进行类型匹配的时候 , 不光会匹配相同类型的异常对象 , 也会捕捉目标异常类型的子类对象 .

4. finally

在写程序时, 有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源 :网络连接、数据库
连接、 IO 流等, 在程序正常或者异常退出时,必须要对资源进进行回收 。另外,因为 异常会引发程序的跳转,可能
导致有些语句执行不到 finally 就是用来解决这个问题的。
注意: finally 中的代码一定会执行的,一般在 finally 中进行一些资源清理的扫尾工作
语法格式:
try{// 可能会发生异常的代码
}catch(异常类型 e){// 对捕获到的异常进行处理
}finally{// 此处的语句无论是否发生异常,都会被执行到
}// 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
        Scanner scan = new Scanner(System.in);try{int n = scan.nextInt();System.out.println("抛出异常之前的代码可以被执行");System.out.println(10/n);System.out.println("抛出异常之后的代码不会被执行");}catch(ArithmeticException a){a.printStackTrace();//打印异常的详细信息System.out.println("这是算术异常");}//多个异常的处理方式是完全相同,中间可以用 | 隔开catch(ArrayIndexOutOfBoundsException | NullPointerException n){n.printStackTrace();System.out.println("这是数组越界异常和空指针异常");}//通过一个catch捕获所有的异常,即多个异常catch (Exception e){e.printStackTrace();System.out.println("这是异常");}//finally中的代码一定会执行的,不管是否发生异常finally {System.out.println("finally中的代码一定会被执行");scan.close();}System.out.println("该代码在没有抛出异常或异常被捕获执行,异常未处理不执行");

    public static int meth(){try{System.out.println(10/0);return 0;}catch(ArithmeticException a){return 1;}finally{return 2;}}public static void main(String[] args) {System.out.println(meth());// 输出:2}
finally 执行的时机是在方法返回之前 (try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果
finally 中也存在 return 语句 , 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return.

finally 中使用 return 是不推荐的,因为:

  1. 容易混淆逻辑:掩盖了 trycatch 的返回结果。
  2. 难以调试:可能会导致不可预测的行为,特别是在处理资源释放时。

异常的处理流程

关于 " 调用栈 "
方法之间是存在相互调用关系的 , 这种调用关系我们可以用 " 调用栈 " 来描述 . JVM 中有一块内存空间称为
" 虚拟机栈 " 专门存储方法之间的调用关系 . 当代码中出现异常的时候 , 我们就可以使用 e.printStackTrace();
方式查看出现异常代码的调用栈 .
如果本方法中没有合适的处理异常的方式 , 就会沿着调用栈向上传递, 如果向上一直传递都没有合适的方法处理异常 , 最终就会交给 JVM 处理 , 程序就会异常终止 ( 和我们最开始未使用 try catch 时是一样的 )
异常处理流程总结
程序先执行 try 中的代码
如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 .
如果找到匹配的异常类型 , 就会执行 catch 中的代码
如果没有找到匹配的异常类型 , 就会将异常向上传递到上层调用者 .
无论是否找到匹配的异常类型 , finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
如果上层调用者也没有处理的了异常 , 就继续向上传递 .
一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止

自定义异常类

Java 中虽然已经内置了丰富的异常类 , 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我们实际情况的异常结构.
注意事项
自定义异常通常会继承自 Exception 或者 RuntimeException
继承自 Exception 的异常默认是受查异常
继承自 RuntimeException 的异常默认是非受查异常
实现一个用户登录功能:
输入用户名和密码,比较是否与我们原有的用户名和密码相同,如果用户名不同,抛出我们自定义的NameException异常,并重新输入用户名,如果密码不同,抛出我们自定义的PasswordException异常,并重新输入密码,直到相同,跳出循环。
//自定义异常
//继承RuntimeException
public class NameException extends RuntimeException{//构造方法public NameException() {}public NameException(String message) {super(message);}
}
//自定义异常
//继承RuntimeException
public class PasswordException extends RuntimeException{//构造方法public PasswordException() {}public PasswordException(String message) {super(message);}
}
import java.util.Scanner;public class Login{private String name = "admin";private String password = "123456";public void Loginifor(String name,String password){if(!this.name.equals(name)){throw new NameException("用户名输入错误,请重新输入用户名:");//抛出异常}if(!this.password.equals(password)){throw new PasswordException("密码输入错误,请重新输入密码:");//抛出异常}System.out.println("登录成功");}public static void main(String[] args) {Login login = new Login();Scanner scan = new Scanner(System.in);System.out.print("请输入用户名:");String name1 = scan.nextLine();System.out.print("请输入密码:");String password1 = scan.nextLine();while(true){try{login.Loginifor(name1,password1);//可能会抛出异常break;//抛出异常后,该代码不被执行  输入正确后,跳出循环}catch (NameException n){ //捕获异常//处理异常n.printStackTrace();//打印异常name1=scan.nextLine();//重新输入用户名}catch (PasswordException p){p.printStackTrace();password1=scan.nextLine();}}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com