大话Java异常丨【奔跑吧!JAVA】
【摘要】 大话Java异常
异常
异常的概述
- 异常就是不正常的意思,Java语言中主要是指程序在运行阶段产生的错误
- Throwable(可抛出的,可扔出的)
- java.lang.Throwable 类是Java程序所有错误或异常的超类
- 主要有两个字类
- Error
- Error主要描述比较严重的错误
- 无法通过编程来解决的重大的错误
- Exception
- Exception主要m描述比较轻量级的错误
- 可以通过编程来解决
- Error
Exception类的主要分类
RuntimeException -> 运行时异常,也叫非检测性异常类
- 非检测性异常类就是指b编译阶段无法被编译器检测出来的异常
- 主要子类
- ArithmeticException -> 算数异常类
- ArrayIndexOutOfBoundsException(间接子类) -> 数组下标异常类
- NullPointerException -> 空指针异常
- ClassCastException -> 类型转换异常
- NumberFormatException(间接子类)-> 数字格式异常
- 注意
- 当程序的执行过程中产生异常,若没有手动进行处理,则由Java虚拟机采用默认的方式进行处理,默认方式是打印异常名称、异常原因以及异常发生的位置并终止程序,后序代码无法被执行
IOException和其他异常类 -> 其他异常类,也叫做非检测性异常
案例
TestRuntimeException.java
package demo1;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
* ArithmeticException -> 算数异常类
ArrayIndexOutOfBoundsException(间接子类) -> 数组下标异常类
NullPointerException -> 空指针异常
ClassCastException -> 类型转换异常
NumberFormatException(间接子类)-> 数字格式异常
*/
public class TestRuntimeException {
public static void main(String[] args) {
// 观察检测性异常
// FileInputStream fis = new FileInputStream("c:/a.txt");
// java.lang.ArithmeticException 算数异常
int a = 10;
int b = 0;
if (b != 0) {
System.out.println(a/b);
}
// java.lang.ArrayIndexOutOfBoundsException 数组下标越界异常
int[] arr = new int[3];
int num = 3;
if (num >= 0 && num < arr.length) {
System.out.println(arr[num]);
}
// java.lang.NullPointerException
String str = null;
if (str != null) {
System.out.println(str.length());
}
// java.lang.ClassCastException
Exception ex = new Exception();
if (ex instanceof IOException) {
IOException ie = (IOException) ex;
}
// java.lang.NumberFormatException
String s = "12be";
if (s.matches("\\d+")) {
System.out.println(Integer.parseInt(s));
}
System.out.println("运行程序结束");
}
}
异常处理
运行时异常的处理方式
- 对于绝大数运行时异常来说,都可以通过条件判断避免异常的发生
异常的捕获
-
语法格式
try{
可能产生异常对象的语句块
}catch(异常类型 引用名){
针对当前异常类型对象的处理语句块
}
… (可以写多个catch)
finally{
无论是否发生异常,都应该执行的语句块
} -
注意事项
- 当捕获的结构中有多个catch分支时,切记小范围的异常类型放在大范围的异常类型上面
- 懒人写法:
catch(Exception e) {…}
-
执行流程
try { a; b; // 可能产生异常的语句 c; } catch (Exception e) { e; } finally { f; }
- 当没有产生异常的时候,程序的执行流程是:a b c f
- 当产生异常时,程序的执行流程是: a b e f
-
案例
- TestExceptionCatch.java
package demo2; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class TestExceptionCatch { public static void main(String[] args) { // 声明引用指向本类的对象,用于读取文件中的内容 FileInputStream fis = null; try { // 随时可能产生文件找不到y异常对象, new FileNotFoundException() fis = new FileInputStream("d:/a.txt"); } catch (FileNotFoundException e) { // 打印异常的名称、异常原因、异常的位置等信息 e.printStackTrace(); } try { fis.close(); } catch (IOException e) { e.printStackTrace(); } catch (NullPointerException e) { // System.out.println("输出"); e.printStackTrace(); } } }
- TestFinally.java
package demo3; public class TestFinally { public static void main(String[] args) { int a = 10; int b = 0; try { System.out.println(a/b); } catch (Exception e) { e.printStackTrace(); return ; } finally { System.out.println("无论是否发生异常都会执行"); } System.out.println("程序结束"); } }
java.lang.ArithmeticException: / by zero 无论是否发生异常都会执行 at demo3.TestFinally.main(TestFinally.java:9)
异常的抛出
- 基本概念
- 某些特殊的场合中,当产生异常后却无法直接处理/不想处理时,此时就可以将异常转移给当前方法的调用者,这就叫异常的抛出
- 语法格式
- 返回值类型 方法名称(形参列表) throws 异常类型{…}
- 方法重写的原则
- 要求方法名相同、参数列表相同、返回值类型也相同,从jdk1.5开始允许返回子类类型
- 范围权限不能变小,可以相同或者变大
- 不能抛出更大的异常
- 注意
- 子类中重写以后的方法可以选择抛出与父类一样的异常、更小的异常、不抛出异常,但是不能抛出更大的异常、不同的异常
- 案例
A.java
SubA.javapackage demo4; import java.io.IOException; public class A { public void show() throws IOException{ System.out.println("A"); } }
package demo4; import java.io.IOException; import java.io.FileNotFoundException; import javax.print.PrintException; public class SubA extends A{ @Override // public void show() throws IOException { // public void show() throws FileNotFoundException { // public void show() throws PrintException { // public void show() throws Exception { public void show() { } }
显然不能抛出更大的异常
自定义异常
-
自定义异常的由来
- Java官方库中虽然提供了大量的异常类,但不足以描述现实生活中所有的异常情况。当出现官方库中没有m描述的异常情况,这个时候就需要程序员自定义异常类加以描述,使得异常信息更加具备针对性和可读性
-
自定义异常的流程
- 自定义类继承自Exception类或者Exception类的子类
- 提供两个版本的构造方法,一个是无参构造方法,另一个是字符串做参数的构造方法
-
自定义异常 – >案例1
- Person.java
package demo5; public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) throws Exception { super(); setName(name); setAge(age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) throws Exception { if(age > 0 && age < 150) { this.age = age; } else { // System.out.println("年龄不合理"); // 手动产生一个异常对象并抛出 // throw new Exception(); throw new AgeException("年龄不合理!"); } System.out.println("产生异常的效果"); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
- AgeException.java
package demo5; public class AgeException extends Exception { /** * */ private static final long serialVersionUID = 1L; // 自定义无参的构造方法 public AgeException() { } // 自定义使用字符串作为参数的构造方法 public AgeException(String msg) { super(msg); } }
- TestPerson.java
package demo5; public class TestPerson { public static void main(String[] args) { Person p = null; try { p = new Person("张三", -12); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(p); } }
demo5.AgeException: 年龄不合理! null at demo5.Person.setAge(Person.java:33) at demo5.Person.<init>(Person.java:15) at demo5.TestPerson.main(TestPerson.java:8)
-
自定义异常 – > 案例2
- Student.java
package demo6; public class Student { private String name; private int id; public Student() { super(); } public Student(String name, int id) throws IDException { super(); setName(name); setId(id); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) throws IDException { if (id > 0) { this.id = id; } else { // System.out.println("学号不合理"); throw new IDException("学号不合理"); } System.out.println("结束"); } @Override public String toString() { return "Student [name=" + name + ", id=" + id + "]"; } }
- IDException.java
package demo6; public class IDException extends Exception { /** * */ private static final long serialVersionUID = 1L; public IDException() { } public IDException(String msg) { super(msg); } }
- TestStudent.java
package demo6; public class TestStudent { public static void main(String[] args) throws IDException { /*Student stu = null; try { stu = new Student("小王", -5); } catch (IDException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ Student stu = new Student("小王", -5); System.out.println(stu); } }
Exception in thread "main" demo6.IDException: 学号不合理 at demo6.Student.setId(Student.java:30) at demo6.Student.<init>(Student.java:14) at demo6.TestStudent.main(TestStudent.java:14)
此处有一点要注意,在案例一的TestPerson中,在main函数中,我们使用try…catch语句,异常由内部进行处理,会打印后面的语句
而在案例二的TestStudent中,我们将异常直接交给main函数处理,也就是交给虚拟机处理,所以并不会执行后面的语句
异常对象的抛出
- throw new 异常类型()
- 例如:
- throw new Exception()
最后简单介绍一下throws和throw的区别
throws和throw的区别
- throws
- 用在方法声明后面,跟的是异常类名
- 可以跟多个异常类名,用逗号隔开
- 表示抛出异常,由该方法的调用者来处理
- throws表示出现异常的一种可能性,并不一定会发生这些异常
- throw
- 用在方法体内,跟的异常对象名
- 只能抛出一个异常对象名
- 表示抛出异常,由方法体内的语句实现
- throw则是抛出了异常,执行throw则一定抛出了某种异常
【奔跑吧!JAVA】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/265241
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)