异常
-
异常就是程序出现了不正常的情况
-
-
-
都是Exception类及其子类
-
必须显示处理,否则程序就会发生错误,无法通过编译
-
-
运行时异常
-
都是RuntimeException类及其子类
-
无需显示处理,也可以和编译时异常一样处理
-
-
把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
-
控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置
我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码
public void 方法() throws 异常类名 { }
示例代码
public class ExceptionDemo { public static void main(String[] args) throws ParseException{ System.out.println("开始"); // method(); method2(); System.out.println("结束"); } //编译时异常 public static void method2() throws ParseException { String s = "2048-08-09"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); System.out.println(d); } //运行时异常 public static void method() throws ArrayIndexOutOfBoundsException { int[] arr = {1, 2, 3}; System.out.println(arr[3]); } }
-
这个throws格式是跟在方法的括号后面的
-
编译时异常必须要进行处理,两种处理方案:try...catch …或者 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
-
-
throw new 异常();
-
注意
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常 | 表示手动抛出异常对象,由方法体内的语句处理 |
示例代码
public class ExceptionDemo8 { public static void main(String[] args) { //int [] arr = {1,2,3,4,5}; int [] arr = null; printArr(arr);//就会 接收到一个异常. //我们还需要自己处理一下异常. } private static void printArr(int[] arr) { if(arr == null){ //调用者知道成功打印了吗? //System.out.println("参数不能为null"); throw new NullPointerException(); //当参数为null的时候 //手动创建了一个异常对象,抛给了调用者,产生了一个异常 }else{ for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } }
try { 可能出现异常的代码; } catch(异常类名 变量名) { 异常的处理代码; }
-
-
程序从 try 里面的代码开始执行
-
出现异常,就会跳转到对应的 catch 里面去执行
-
执行完毕之后,程序还可以继续往下执行
-
public class ExceptionDemo01 { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); } public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[3]); System.out.println("这里能够访问到吗"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("你访问的数组索引不存在,请回去修改为正确的索引"); } } }
-
如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
-
如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了 当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
-
如果出现的问题没有被捕获,那么程序如何运行?
那么try...catch就相当于没有写.那么也就是自己没有处理. 默认交给虚拟机处理.
-
同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
public class ExceptionDemo02 { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); } public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException(); System.out.println("这里能够访问到吗"); } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException(); // e.printStackTrace(); //public String getMessage():返回此 throwable 的详细消息字符串 // System.out.println(e.getMessage()); //Index 3 out of bounds for length 3 //public String toString():返回此可抛出的简短描述 // System.out.println(e.toString()); //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 //public void printStackTrace():把异常的错误信息输出在控制台 e.printStackTrace(); // java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 // at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18) // at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11) } } }
-
键盘录入学生的姓名和年龄,其中年龄为18 - 25岁,超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止
-
实现步骤
-
创建学生对象
-
键盘录入姓名和年龄,并赋值给学生对象
-
如果是非法数据就再次录入
-
代码实现
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age >= 18 && age <= 25){ this.age = age; }else{ //当年龄不合法时,产生一个异常 throw new RuntimeException("年龄超出了范围"); } } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试类
public class ExceptionDemo12 { public static void main(String[] args) { // 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁, // 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in); System.out.println("请输入姓名"); String name = sc.nextLine(); s.setName(name); while(true){ System.out.println("请输入年龄"); String ageStr = sc.nextLine(); try { int age = Integer.parseInt(ageStr); s.setAge(age); break; } catch (NumberFormatException e) { System.out.println("请输入一个整数"); continue; } catch (AgeOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("请输入一个符合范围的年龄"); continue; } /*if(age >= 18 && age <=25){ s.setAge(age); break; }else{ System.out.println("请输入符合要求的年龄"); continue; }*/ } System.out.println(s); } }
-
当Java中提供的异常不能满足我们的需求时,我们可以自定义异常
-
实现步骤
-
定义异常类
-
写继承关系
-
提供空参构造
-
提供带参构造
-
代码实现
public class AgeOutOfBoundsException extends RuntimeException { public AgeOutOfBoundsException() { } public AgeOutOfBoundsException(String message) { super(message); } }
学生类
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age >= 18 && age <= 25){ this.age = age; }else{ //如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常 throw new AgeOutOfBoundsException("年龄超出了范围"); } } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试类
public class ExceptionDemo12 { public static void main(String[] args) { // 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁, // 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in); System.out.println("请输入姓名"); String name = sc.nextLine(); s.setName(name); while(true){ System.out.println("请输入年龄"); String ageStr = sc.nextLine(); try { int age = Integer.parseInt(ageStr); s.setAge(age); break; } catch (NumberFormatException e) { System.out.println("请输入一个整数"); continue; } catch (AgeOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("请输入一个符合范围的年龄"); continue; } /*if(age >= 18 && age <=25){ s.setAge(age); break; }else{ System.out.println("请输入符合要求的年龄"); continue; }*/ } System.out.println(s); } }
-
可能包含或不包含非null值的容器对象
方法名 | 说明 |
---|---|
static <T> Optional<T> of(T value) | 获取一个Optional对象,封装的是非null值的对象 |
static <T> Optional<T> ofNullable(T value) | 获取一个Optional对象,Optional封装的值对象可以是null也可以不是null |
示例代码
public class OptionalDemo1 { public static void main(String[] args) { //method1(); //public static <T> Optional<T> ofNullable(T value) //获取一个Optional对象,Optional封装的值对象可以是null也可以不是null //Student s = new Student("zhangsan",23); Student s = null; //ofNullable方法,封装的对象可以是null,也可以不是null。 Optional<Student> optional = Optional.ofNullable(s); System.out.println(optional); } private static void method1() { //static <T> Optional<T> of(T value) 获取一个Optional对象,封装的是非null值的对象 //Student s = new Student("zhangsan",23); Student s = null; //Optional可以看做是一个容器,里面装了一个引用数据类型的对象。 //返回值就是Optional的对象 //如果使用of方法,封装的对象如果为空,那么还是会抛出空指针异常 Optional<Student> optional1 = Optional.of(s); System.out.println(optional1); } }
方法名 | 说明 |
---|---|
T get() | 如果存在值,返回值,否则抛出NoSuchElementException |
boolean isPresent() | 如果存在值,则返回true,否则为false |
示例代码
public class OptionalDemo2 { public static void main(String[] args) { //get() 如果存在值,返回值,否则抛出NoSuchElementException //public boolean isPresent() 判断Optional所封装的对象是否不为空,如果不为空返回true , 否则返回false //Student s = new Student("zhangsan",23); Student s = null; Optional<Student> optional = Optional.ofNullable(s); //如果封装的是一个null,那么通过get方法再次获取会抛出NoSuchElementException。 if(optional.isPresent()){ Student student = optional.get(); System.out.println(student); }else{ System.out.println("Optional封装的对象为空"); } } }
方法名 | 说明 |
---|---|
T orElse(T other) | 如果不为空,则返回具体的值,否则返回参数中的值 |
T orElseGet(Supplier<? extends T> supplier) | 如果不为空,则返回具体的值,否则返回由括号中函数产生的结果 |
void ifPresent (Consumer<? super T> action) | 如果不为空,则使用该值执行给定的操作,否则不执行任何操作 |
void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) | 如果不为空,则使用该值执行给定的操作,否则执行给定的基于空的操作 |
示例代码
public class OptionalDemo3 { public static void main(String[] args) { //method1(); //method2(); //method3(); //method4(); } private static void method4() { //Student s = new Student("zhangsan",23); Student s = null; Optional<Student> optional = Optional.ofNullable(s); //public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)、 //如果不为空,则使用该值执行给定的操作,否则执行给定的基于空的操作。 optional.ifPresentOrElse(student -> System.out.println(student), ()->System.out.println("为空了")); } private static void method3() { //Student s = new Student("zhangsan",23); Student s = null; Optional<Student> optional = Optional.ofNullable(s); //ifPresent (Consumer<? super T> action) //如果不为空,则使用该值执行给定的操作,否则不执行任何操作 optional.ifPresent(student -> System.out.println(student)); } private static void method2() { Student s = new Student("zhangsan",23); //Student s = null; Optional<Student> optional = Optional.ofNullable(s); //orElseGet(Supplier<? extends T> supplier) //如果不为空,则返回具体的值,否则返回由括号中函数产生的结果 Student student = optional.orElseGet(()-> new Student("lisi" , 24)); System.out.println(student); } private static void method1() { //Student s = new Student("zhangsan",23); Student s = null; Optional<Student> optional = Optional.ofNullable(s); //orElse(T other) 如果不为空,则返回具体的值,否则返回参数中的值 Student student = optional.orElse(new Student("lisi", 24)); System.out.println(student); } }