异常情况是指程序在运行时,可能由与外部系统的条件变更(与我们一厢情愿所设想的不一设)而导致程序可能会出错的情况,
JVM给我们编程提供了简单方便的异常处理方式,上手异常之前我们需要了解异常的体系结构
其中Error为错误,是程序无法处理的,如OutOfMemoryError、ThreadDeath等,出现这种情况你唯一能做的就是听之任之,交由JVM来处理,不过JVM在大多数情况下会选择终止线程。
而Exception是程序可以处理的异常。它又分为两种CheckedException(受捡异常也叫编译时异常),一种是UncheckedException(不受检异常也叫运行时异常RuntimeException)。其中CheckException发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。而UncheckedException发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的,难以排查,我们一般都需要纵观全局才能够发现这类的异常错误,所以在程序设计中我们需要认真考虑,好好写代码,尽量处理异常,即使产生了异常,也能尽量保证程序朝着有利方向发展。
Java具有代码级的强制性异常检测机制,即许多常见的可预料的异常可能都必须编写代码处理,否则就无法编译通过。 一个程序编译时都有大大小小的错误与异常,一个合格的程序都是调试调出来的,异常的处理也能体现出一个程序员的经验也素养。
异常的关键词有try-catch,throw,throws,finally
try-catch
如果一段代码可能会抛出异常---编译器检测或程序员认为会,就需要将这些代码放在try catch块中,如下代码示例;这很好理解:try指“尝试”执行可能出现异常的代码,如果成功,则乎略备用方案,即(B)区的代码;但如失败,代码会catch(捕获)到一个异常对象,放弃(A)计划,开始执行(B)计划!
try{
可能抛出异常的代码. . .
//如果没有问题出理,执行如下面的代码
(A)其它计算代码…
}catch(Exception ef){
//如果出现异常后执行的代码:
(B)出了异常情况的计算代码. . .
}
try{
System.out.println("请输入除数:");//可能出现错误,除数不能为0
b=input.nextInt();
System.out.println("商:"+(a/b));
}
catch (ArithmeticException e){
System.out.println("除数不能为0"); //出现错误,输入的除数为0
}
throw和throws
throw表示主动抛出一个明确的异常(可自定义)
throws往往用来申明异常,即在类后申明该类执行可能会产生的异常
throw 是语句抛出一个异常;throws 是方法抛出一个异常;
throws可以单独使用,但throw不能;
throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使用,然后再由处理异常的方法捕获。
public void sanjiao(int a,int b, int c) throws MyException {//throws声明异常方法
if(a+b>c&&a+c>b&&a-b<c&&a-b<c){
System.out.println("能构成三角形");
}else {
throw new MyException("不能构成三角形");//抛出异常
}
}
finalli是结束语段,
计算机的资源,所以不管是在程序是否正常执行,都必须关闭. 那这些必须关闭的资源应该放在那里呢?放在try中,不行吧,如果出现异常,那try中的代码就不会执行了,如果放在catch中,那如果ctach捕获的异常不一样,那也不会执行,所以java就给我们准备了这样一个东西,这就是finally块,finally块表示程序不管是否发生异常,总会执行。
try {// 放的是可能会出现异常的代码
Scanner input = new Scanner(System.in);
System.out.println("请输入被除数:");
int num1 = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println("计算结果如下:");
System.out.println(num1 + "/" + num2 + "=" + (num1 / num2));
System.out.println("======代码正常执行完==========");
} catch (ArithmeticException e) { // catch是捕获异常,并进行处理
// 需要注意,我们这个catch捕获的只能是ArithmeticException异常或者其子类异常,对其他异常不捕获
e.printStackTrace();// 可以在控制台打印详细的异常信息,在开发阶段使用,便于调试代码
// 异常的处理,我们简单输出一句话,但是在真实的项目中,不能只是输出一句话,而是要做相应的处理
System.out.println("你丫的没读过小学吗?不知道除数不能为0吗");
} catch (InputMismatchException e) {
System.out.println("你丫不知道什么是数字吗,乱输个啥");
} catch (Exception e) { // Exception是所有异常类的父类,所以要写在最后
System.out.println("哎,我也不知道怎么办了");
} finally {//不管是否异常都会执行
System.out.println("================程序结束!!!!=====================");
}
自定义异常(用于JVM没有提供符合心意的解决方法,自己写异常方法)
自定义异常需要继承Exception
public class MyException extends Exception{
public MyException() {
super();
}
public MyException(String msg) {
super(msg);
}
public MyException(Throwable cause) {
super(cause);
}
public MyException(String msg, Throwable cause) {
super(msg, cause);
}
自定义异常的使用也跟系统异常使用一样。
public void sanjiao(int a,int b, int c) throws MyException {//,MyExceptin是自定义异常
if(a+b>c&&a+c>b&&a-b<c&&a-b<c){
System.out.println("能构成三角形");
}else {
throw new MyException("不能构成三角形");//抛出自定义异常
}
}
几种常见的异常
1、算术异常类:ArithmeticException 操作运算的时候抛出,可能除数为0,可能字符为字母。
2、空指针异常类:NullpointerException 调用未初始化或不存在的对象。
3、类型强制转换异常:ClassCastException 高精度转低精度没有强制转型
4、数组下标越界异常:ArrayIndexOutOfBoundsException 数组下标超出数组长度
5、文件未找到异常:FileNotFoundException 文件路径错误导致找不到文件
6、操作数据库异常:SQLException SQL语句错误
7、I/O 异常的根类:IOException 找不到指定路径
————————————————
扩展,如何在抛出异常后继续执行程序?如何重新进行循环?
重新调用一个方法,这个方法需要与被中断方法有一定联系。
package demo06;
import java.util.Scanner;
public class Ave {
Scanner input = new Scanner(System.in);
private int count;
double sum;
int b = 0;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void Input(int a) throws Exception{
if(a < 0){
throw new DidnotNullException("请输入正数或零!!");
}
}
public void forwardin(int a) throws Exception {
for (int i = 0; i < a; i++) {
b = input.nextInt();
Input(b);
sum += b;
setCount(getCount() + 1);
}
}
public double backin(int a,double sum) throws Exception{
for (int i = count; i < a; i++) {
b = input.nextInt();
sum += b;
Input(b);
}
return sum;
}
public static void main(String[] args) throws Exception{
Ave ave = new Ave();
Scanner input = new Scanner(System.in);
System.out.println("请问你要计算几个整数的平均数:");
int a = input.nextInt();
double hh = 0;
System.out.println("请输入" + a + "个整数:");
try{
ave.forwardin(a);
System.out.println("平均值为:" + ave.sum/a);
}catch (DidnotNullException e){
System.out.print("DidnotNullException" + e.getMessage() + "请重新输入:");
hh = ave.backin(a,ave.sum);//重新调用一个方法并传参
System.out.println("平均值为:" + hh/a);
}
}
}