前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JAVA中异常处理

JAVA中异常处理

作者头像
星哥玩云
发布2022-09-14 20:14:24
8870
发布2022-09-14 20:14:24
举报
文章被收录于专栏:开源部署

1、异常概述

异常:异常就是Java程序在运行过程中出现的错误。 异常由来:问题也是现实生活中一个具体事务,也可以通过java的类的形式进行描述,并封装成对象。其实就是Java对不正常情况进行描述后的对象体现。 我们见过的异常,角标越界异常,空指针异常

jvm对异常的默认处理方案

如果程序出现了问题,我们没有做任何处理,最终jvm会做出默认的处理。

把异常的名称,原因及出现的问题等信息输出在控制台。

同时会结束程序。

案例一:

代码语言:javascript
复制
public static void main(String[] args) {
		//第一阶段
		int a = 10;
		int b = 0;
		System.out.println(a / b);
}

运行结果

代码语言:javascript
复制
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at cn.itcast_01.ExceptionDemo.main(ExceptionDemo.java:29)

案例二:

代码语言:javascript
复制
public static void main(String[] args) {
    int[] arr = {10,9,8};
    System.out.println(arr[3]);
}
代码语言:javascript
复制
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at cn.itcast_01.ExceptionDemo.main(ExceptionDemo.java:27)

案例三:

代码语言:javascript
复制
public static void main(String[] args) {
    String str = null;
    System.out.println(str.length());
}
代码语言:javascript
复制
Exception in thread "main" java.lang.NullPointerException
	at cn.itcast_01.ExceptionDemo.main(ExceptionDemo.java:26)

2、异常的分类

  • 编译时异常
  • 运行时异常
  • 严重错误问题
image20200110155013328.png
image20200110155013328.png

编译时异常

​ 除了RuntimeException及其子类,Exception中所有的子类都是,这种异常必须要处理,要不编译通不过

运行时异常

​ RuntimeException及其子类都是,这种异常不用处理,编译会通过,不过这样的程序会有安全隐患,遇到这种异常是需要改代码的

严重错误问题

用Error进行描述,这个问题发生后,一般不编写针对代码进行处理,而是要对程序进行修正.通常都是由虚拟机抛出的问题

3、异常处理方案

  • JVM的默认处理方案
  • try…catch…finally
  • throws

try…catch…finally的异常处理方案

3.1、格式

代码语言:javascript
复制
try {
	可能出现问题的代码;
}catch(异常名 变量) {
	针对问题的处理;
}finally {
	释放资源;
}

3.2、变形格式

代码语言:javascript
复制
try {
    可能出现问题的代码;
}catch(异常名 变量) {
    针对问题的处理;
}

3.3、注意事项

​ A:try里面的代码越少越好

​ B:catch里面必须有内容,哪怕是给出一个简单的提示

**案例演示一:**一个异常的处理

代码语言:javascript
复制
public static void main(String[] args) {
    // 第一阶段
    int a = 10;
    // int b = 2;
    int b = 0;

    try {
    	System.out.println(a / b);//有异常,被捕获
    } catch (ArithmeticException ae) {
    	System.out.println("除数不能为0");//异常处理代码
    }

    // 第二阶段
    System.out.println("over");
}

程序运行结果:

代码语言:javascript
复制
除数不能为0
over

**案例演示二:**两个异常的处理

格式:

代码语言:javascript
复制
a:每一个写一个try...catch
    try {
    	可能出现问题的代码;
	}catch(异常名 变量) {
    	针对问题的处理;
	}
b:写一个try,多个catch
    try{
        ...
    }catch(异常类名 变量名) {
        ...
    }
	catch(异常类名 变量名) {
    	...
	}

a方案的实现

代码语言:javascript
复制
	public static void method() {
		int a = 10;
		int b = 0;
		try {
			System.out.println(a / b);
		} catch (ArithmeticException e) {
			System.out.println("除数不能为0");
		}

		int[] arr = { 1, 2, 3 };
		try {
			System.out.println(arr[3]);
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你访问了不该的访问的索引");
		}

		System.out.println("over");
	}

b方案的实现

代码语言:javascript
复制
public static void method3() {
    int a = 10;
    int b = 0;
    int[] arr = { 1, 2, 3 };
    try {
    	System.out.println(arr[3]);
    	System.out.println(a / b);
    } catch (ArithmeticException e) {
    	System.out.println("除数不能为0");
    } catch (ArrayIndexOutOfBoundsException e) {
    	System.out.println("你访问了不该的访问的索引");
    }
    System.out.println("over");
}

注意问题:多个异常,爷爷一定要在儿子或孙子后面

代码语言:javascript
复制
public static void method4() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };

		// 爷爷在最后
		try {
			System.out.println(a / b);
			System.out.println(arr[3]);
			System.out.println("这里出现了一个异常,你不太清楚是谁,该怎么办呢?");
		} catch (ArithmeticException e) {
			System.out.println("除数不能为0");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你访问了不该的访问的索引");
		} catch (Exception e) {
			System.out.println("出问题了");
		}

		// 爷爷在前面是不可以的
		// try {
		// System.out.println(a / b);
		// System.out.println(arr[3]);
		// System.out.println("这里出现了一个异常,你不太清楚是谁,该怎么办呢?");
		// } catch (Exception e) {   //Error 编译期会报错
		// System.out.println("出问题了");
		// } catch (ArithmeticException e) {
		// System.out.println("除数不能为0");
		// } catch (ArrayIndexOutOfBoundsException e) {
		// System.out.println("你访问了不该的访问的索引");
		// }

		System.out.println("over");
	}

JDK7出现了一个新的异常处理方案:(不推荐使用)

代码语言:javascript
复制
public static void method() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };

		
		// JDK7的处理方案
		try {
			System.out.println(a / b);
			System.out.println(arr[3]);
		} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
			System.out.println("出问题了");
		}

		System.out.println("over");
	}

4、编译时异常和运行时异常的区别

Java中的异常被分为两大类:编译时异常和运行时异常。所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常 编译时异常 Java程序必须显示处理,否则程序就会发生错误,无法通过编译 运行时异常 无需显示处理,也可以和编译时异常一样处理

代码语言:javascript
复制
public static void main(String[] args) {
		 int a = 10;
		 int b = 0;
		 if (b != 0) {
		 	System.out.println(a / b);//运行时异常无需显示处理
		 }

		String s = "2014-11-20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		// Date d = sdf.parse(s); 编译期异常必须显示处理
		try {
			Date d = sdf.parse(s);
			System.out.println(d);
		} catch (ParseException e) {
			// e.printStackTrace();
			System.out.println("解析日期出问题了");
		}
}

5、Throwable中的方法

Throwable是java异常继承体系中的顶层父类,所有的异常对象都是从其继承过来。

当程序遇到异常后,JVM会帮我们生产一个异常对象,然后剖出,此时我们可以用catch语句进行捕获,捕获后的异常对象会传递到catch里面的异常参数里;如果没有对异常进行处理,那么异常最终会交给JVM进行处理,JVM会把异常对象的相关信息打印出来。所以我们要学习一下异常对象的几个从Throwable继承过来的方法。

getMessage() 获取异常信息,返回字符串。 toString() 获取异常类名和异常信息,返回字符串,该字符串由以下三部分组成:

(1)此对象的类的 name(全路径名)

(2)": "(冒号和一个空格)

(3)调用此对象 getLocalizedMessage()方法的结果 (默认返回的是getMessage()的内容)

printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。 printStackTrace(PrintStream s) 通常用该方法将异常内容保存在日志文件中,以便查阅。

代码语言:javascript
复制
public static void main(String[] args) {
		String s = "2014-11-20";
		SimpleDateFormat sdf = 
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
            // 创建了一个ParseException对象,然后抛出去,和catch里面进行匹配
			Date d = sdf.parse(s); 
			System.out.println(d);
            //e对象相当于
            // ParseException e = new ParseException();
		} catch (ParseException e) { 
			//printStackTrace()
			//e.printStackTrace();
			 /*
			 上面的输出结果:
			 java.text.ParseException: Unparseable date: "2014-11-20"
				at java.text.DateFormat.parse(DateFormat.java:357)
				at com.tyschool.test.main(ExceptionDemo.java:24)
			  */
			// getMessage()
			// System.out.println(e.getMessage());
			// 输出结果:Unparseable date: "2014-11-20"

			// toString()
			// System.out.println(e.toString());
			// 输出结果:
            //java.text.ParseException: Unparseable date: "2014-11-20"
		}		
		System.out.println("over");
}

6、throws关键字-抛出异常方案

该关键字可以将不想处理的异常交给调用者进行处理。

定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。

有些时候,我们是可以对异常进行处理的,但是又有些时候,我们根本就没有权限去处理某个异常。 或者说,我处理不了,我就不处理了。 为了解决出错问题,Java针对这种情况,就提供了另一种处理方案:抛出。

格式: throws 异常类名 注意:这个格式必须跟在方法的括号后面。

注意: 尽量不要在main方法上抛出异常。 但是我讲课为了方便我就这样做了。

小结: 编译期异常抛出,将来调用者必须处理。 运行期异常抛出,将来调用可以不用处理。

代码演示:

代码语言:javascript
复制
	public static void main(String[] args) {
		System.out.println("今天天气很好");
		try {
			method();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.println("但是就是不该有雾霾");

		method2();
	}

	// 运行期异常的抛出
	public static void method2() throws ArithmeticException {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}

	// 编译期异常的抛出
	// 在方法声明上抛出,是为了告诉调用者,你注意了,我有问题。
	public static void method() throws ParseException {
		String s = "2014-11-20";
		SimpleDateFormat sdf = 
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date d = sdf.parse(s);
		System.out.println(d);
	}

7、throw关键字

在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

代码演示

代码语言:javascript
复制
public static void main(String[] args) {
		// method();
		
		try {
			method2();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void method() {
		int a = 10;
		int b = 0;
		if (b == 0) {
			throw new ArithmeticException();
		} else {
			System.out.println(a / b);
		}
	}

	public static void method2() throws Exception {
		int a = 10;
		int b = 0;
		if (b == 0) {
			throw new Exception();//手动创建异常并扔出
		} else {
			System.out.println(a / b);
		}
	}

8、throws和throw的区别

throws

  • 用在方法声明后面,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,并不一定会发生这些异常

throw

  • 用在方法体内,跟的是异常对象名
  • 只能抛出一个异常对象名
  • 表示抛出异常,由方法体内的语句处理
  • throw则是抛出了异常,执行throw则一定抛出了某种异常

9、处理异常的原则

如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws

举例:感冒了就自己吃点药,这个时候用try的方式对异常进行处理;如果是跌倒骨折了,自己处理不了就去医院。

区别:try处理了,别人就不需要处理;throws的话,别人仍然需要处理。

10、finally关键字

使用格式

代码语言:javascript
复制
格式:try...catch...finally...

finally的特点

被finally控制的语句体一定会执行 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

finally的作用

用于释放资源,在IO流操作和数据库操作中会见到

代码演示

代码语言:javascript
复制
public static void main(String[] args) {
		String s = "2014-11-20";
		SimpleDateFormat sdf = 
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date d = null;
		try {
			// System.out.println(10 / 0);
			d = sdf.parse(s);
		} catch (ParseException e) {
			e.printStackTrace();
			System.exit(0);
		} finally {
			System.out.println("这里的代码是可以执行的");
		}
		System.out.println(d);
	}

finally面试题: (1):final,finally和finalize的区别 final:最终的意思,可以修饰类,成员变量,成员方法 修饰类,类不能被继承 修饰变量,变量是常量 修饰方法,方法不能被重写 finally:是异常处理的一部分,用于释放资源。 一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了 finalize:是Object类的一个方法,用于垃圾回收

(2):如果catch里面有return语句,请问finally里面的代码还会执行吗?

如果会,请问是在return前,还是return后。

答:会,在之前。

参考代码:

代码语言:javascript
复制
	public static void main(String[] args) {
		System.out.println(getInt());
	}

	public static int getInt() {
		int a = 10;
		try {
			System.out.println(a / 0);
			a = 20;
		} catch (ArithmeticException e) {
			a = 30;
			return a;
			/*
			 * return a在程序执行到这一步的时候,这里不是return a而是return 30;这个返回路径就形成了。
			 * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40
			 * 再次回到以前的返回路径,继续走return 30;
			 */
		} finally {
			a = 40;
			return a;//如果这样结果就是40了。
		}
		// return a;
	}

11、自定义异常

  • java不可能对所有的情况都考虑到,所以,在实际的开发中,我们可能需要自己定义异常。
  • 而我们自己随意的写一个类,是不能作为异常类来看的,要想你的类是一个异常类,就必须继承自Exception或者RuntimeException

种类

继承自Exception 继承自RuntimeException

参考代码:

代码语言:javascript
复制
public class MyException extends Exception {
	public MyException() {
	}

	public MyException(String message) {//message就是异常的描述性信息
		super(message);
	}
}

// public class MyException extends RuntimeException {
//
// }
代码语言:javascript
复制
class Teacher {
	public void check(int score) throws MyException {
		if (score > 100 || score < 0) {
			throw new MyException("分数必须在0-100之间");
		} else {
			System.out.println("分数没有问题");
		}
	}

	// 针对MyException继承自RuntimeException
	// public void check(int score) {
	// if (score > 100 || score < 0) {
	// throw new MyException();
	// } else {
	// System.out.println("分数没有问题");
	// }
	// }
}
代码语言:javascript
复制
/*
 * 自定义异常测试类
 */
public class StudentDemo {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入学生成绩:");
		int score = sc.nextInt();

		Teacher t = new Teacher();
		try {
			t.check(score);
		} catch (MyException e) {
			e.printStackTrace();
		}
	}
}

12、异常注意事项

(a)子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏) (b)如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常 ©如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

代码演示

代码语言:javascript
复制
public class ExceptionDemo {

}

class Fu {
	public void show() throws Exception {
	}

	public void method() {
	}
}

class Zi extends Fu {
	@Override
	public void show() throws ArithmeticException {

	}

	@Override
	public void method() {
		// String s = "2014-11-20";
		// SimpleDateFormat sdf = new SimpleDateFormat();
		// Date d = sdf.parse(s);
		// System.out.println(d);
	}
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、异常概述
  • 2、异常的分类
  • 3、异常处理方案
    • 3.1、格式
      • 3.2、变形格式
        • 3.3、注意事项
        • 4、编译时异常和运行时异常的区别
        • 5、Throwable中的方法
        • 6、throws关键字-抛出异常方案
        • 7、throw关键字
        • 8、throws和throw的区别
        • 9、处理异常的原则
        • 10、finally关键字
        • 11、自定义异常
        • 12、异常注意事项
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档