如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理 , 那么JVM是如何处理的呢 ?
注意 : 程序中出现了异常 , 会在当前位置创建此异常的对象 , 对象中包含了异常的信息 , 并把此异常交给本方法的调用者处理
缺点 : 用户体验不好
声明异常—— throws
作用 :
package com.itheima.exception_demo;
import sun.java2d.pipe.SpanShapeRenderer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
声明异常—— throws
格式 : 修饰符 返回值类型 方法名(参数列表) throws 异常类型1 , 异常的类型2... { ... }
举例 : public void show() throws NullPointerException , ArrayIndexOutOfBoundsException { .... }
作用 :
1 表示告知调用者当前的方法可能会出现某些异常,使用时需要注意哦!
2 如果当前方法没有出现任何异常, 那么代码会正常执行
3 如果当前方法中出现了异常 , 会把异常交给本方法调用者处理(甩锅)
需求 :
练习 : 定义两个方法一个运行时期异常 , 一个声明编译时期异常 !
注意 :
1 编译时异常因为在编译时就会检查,所以必须要写在方法后面进行显示声明
2 运行时异常因为在运行时才会发生,所以在方法后面可以不写
3 如果声明多个异常有子父类关系 , 那么只要声明一个父类即可(多态)
*/
public class Exception_Throws {
public static void main(String[] args) throws ParseException{
printArr();// 如果此方法出现了异常 , 会交给jvm进行处理
StringToDate();// 如果此方法出现了异常 , 会交给jvm进行处理
}
// 1 告诉调用者 , 此方法可能会出现异常哦
// 2 如果此方法没有出现异常 , 那么会正常执行
// 3 如果此方法中出现了异常 , 会把此异常交给调用者处理
// 注意 : 如果声明的异常是一个运行时期异常 , 那么此声明可以省略
public static void printArr() /*throws NullPointerException*/ {
int[] arr = null;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
// 1 告诉调用者 , 此方法可能会出现异常哦
// 2 如果此方法没有出现异常 , 那么会正常执行
// 3 如果此方法中出现了异常 , 会把此异常交给调用者处理
// 注意 : 如果声明的异常 是一个编译时期异常 , 那么在编译时期必须处理 , 要么程序无法执行
public static void StringToDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2000-03-11 12:12:12");
}
}
修饰符 返回值类型 方法名(参数列表) {
throw new 异常对象();
}
package com.itheima.exception_demo;
/*
抛出异常演示 :
格式 :
修饰符 返回值类型 方法名(参数列表) {
throw new 异常对象();
}
注意 :
1 抛出异常的格式必须在方法的内部完成
2 如果手动抛出一个异常,下面的代码无法执行
*/
public class Exception_Throw {
public static void main(String[] args) {
System.out.println("家里有一个貌美如花的老婆");
System.out.println("还有一个当官的兄弟");
System.out.println("自己还有一个买卖");
System.out.println("这样的生活你要不要?");
// 程序不想往下执行了 ,怎么做 ???
// 1 自己手动制造出一个异常
// 2 当前异常也是交给了方法的调用者处理 , 也就是jvm处理
// 3 下面代码无法执行
throw new RuntimeException();
// System.out.println("武大郎的标准生活!");
}
}
package com.itheima.exception_demo;
/*
抛出异常存在的意义所在 :
1 在方法中,当传递的参数有误,没有继续运行下去的意义了,则采取抛出处理,表示让该方法结束运行。
2 告诉调用者方法中出现了问题
练习 : 定义一个方法 , 方法的参数接收一个数组 , 在方法中遍历数组 .
需求1 : 如果方法接收的数组为null , 使用输出语句提示
需求2 : 如果方法接收的数组为null , 使用抛出异常解决
思考 : 两种方式的区别在哪里 ?
*/
public class Exception_Throw2 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
arr = null;
// printArr1(arr);
printArr2(arr);// 接收方法返回的异常 , 但是此异常有jvm进行处理
}
// 需求1 : 如果方法接收的数组为null , 使用输出语句提示
public static void printArr1(int[] arr) {
if (arr == null) {
System.out.println("数组为null");
} else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
// 需求2 : 如果方法接收的数组为null , 使用抛出异常解决
public static void printArr2(int[] arr) {
if (arr == null) {
throw new RuntimeException();
} else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
捕获处理异常介绍 : try, catch
捕获异常的格式
try {
try中存放可能会出现问题的代码
1.代码...
2.代码...
3.代码...
} catch (异常类型 变量名) {
4.处理异常方案
打印异常,获取异常原因记录日志......)
}
5.其他代码...
执行方式
多异常捕获处理方案
多个异常,每个异常单独处理
try{
异常1
}catch(异常1){
}
try{
异常2
}catch(异常2){
}
多个异常,一次捕获,多次处理
try{
异常1
异常2
}catch(异常1){
}catch(异常2){
}
多个异常,异常一次捕获,一次处理
try{
异常1
异常2
}catch(Exception e){
}
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
package com.itheima.exception_demo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/*
定义一个方法接收一个生日日期字符串(xxxx年xx月xx)
main方法中让用户输入一个生日日期字符串,调用设计好的方法计算在地球上活了多少天。
要求:如果解析发生异常,捕获异常,提示用户要重新输入生日日期字符串,直到输入正确的日期为止。
思考:设计代此码的过程中想想什么时候捕获异常,什么时候声明异常?
*/
public class ExceptionTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入生日(xxxx-xx-xx):");
while (true) {
String birthday = sc.nextLine();
try {
method(birthday);
break;// 如果生日没有问题结束死循环
} catch (ParseException e) {
System.out.println("录入生日格式有误!");
}
}
}
public static void method(String strDate) throws ParseException {
// 创建日期模板对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 解析字符串
Date date = sdf.parse(strDate);
// 获取生日到1970/1/1 经历的毫秒值
long time1 = date.getTime();
// 当前系统时间到1970/1/1 经历的毫秒值
Date d2 = new Date();
long time2 = d2.getTime();
System.out.println("活了" + (time2 - time1) / (1000L * 60 * 60 * 24) + "天");
}
}