├── java.lang.Throwable
│ ├── java.lang.Error # 一般不编写针对性的代码进行处理
│ └── java.lang.Exception # 可以进行异常的处理
│ ├── 编译时异常(checked)
│ │ ├── IOException
│ │ | ├── FileNotFoundException
│ │ ├── ClassNotFoundException
│ │ ├── ...
│ ├── 运行时异常(unchecked)
│ │ ├── NullPointerException
│ │ ├── ArrayIndexOutOfBoundsException
│ │ ├── StringIndexOutOfBoundsException
│ │ ├── ClassCastException
│ │ ├── NumberFormatException
│ │ ├── InputMismatchException
│ │ ├── ArithmeticException
│ │ ├── ...
Error
Error不在处理范围之内(不能处理),错了就改
public static void main(String[] args) {
// 栈溢出:Exception in thread "main" java.lang.StackOverflowError
// main(args);
// 堆溢出:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Integer[] arr = new Integer[1024 * 1024 * 1024];
int num = 1024*1024*1024*2 - 1;
System.out.println(num);
}
Exception
Exception 分为编译时异常和运行时异常。
运行时异常(改代码)
运行时异常在开发中一般不考虑 try-catch 处理。因为使用 try-catch处理,在编译时不会报错,但是运行时还是会报错,相当于将报错延后到运行时出现。
常见的运行时异常如下:
//
public class ExceptionDemoTest {
public static void main(String[] args) {
// 输入不匹配:Exception in thread "main" java.util.InputMismatchException
System.out.print("请输入分数:");
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
System.out.println(score);
}
@Test
public void test1() {
int[] numbers = null;
// 空指针:Exception in thread "main" java.lang.NullPointerException
System.out.println(numbers[2]);
}
@Test
public void test4() {
String str = null;
// 空指针:java.lang.NullPointerException
System.out.println(str.charAt(0));
}
@Test
public void test2() {
// 数组角标越界:java.lang.ArrayIndexOutOfBoundsException: 3
int[] numbers1 = new int[3];
System.out.println(numbers1[3]);
}
@Test
public void test3() {
String str0 = "abc";
// 字符串角标越界:java.lang.StringIndexOutOfBoundsException: String index out of range: 3
System.out.println(str0.charAt(0) + " - " + str0.charAt(1) + " - " + str0.charAt(2)+ " - " + str0.charAt(3));
}
@Test
public void test5() {
// java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
Object object = new Date();
String str = (String)object;
}
@Test
public void test6() {
String str = "123a";
// java.lang.NumberFormatException: For input string: "123a"
int i = Integer.parseInt(str);
System.out.println(i);
}
@Test
public void test7() {
System.out.print("请输入分数:");
// InputMismatchException
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
System.out.println(score);
}
@Test
public void test9() {
// java.lang.ArithmeticException: / by zero
System.out.println(10 / 0);
}
}
编译时异常
处理异常的方式:try-catch 或者 try-catch-finally / throws 异常类型
try-catch-finally
- 语法
try {
// 可能出现异常的代码
} catch (异常类型1 变量名1) {
// 处理异常方式1
// String msg = 变量名1.getMessage();
// System.out.println(msg);
// e.printStackTrace();
} catch (异常类型2 变量名2) {
// 处理异常方式2
}
// ...
finally { // 可选
// 一定会执行的代码
}
- 说明
finally是可选的,finally中的代码一定会被执行- 使用
try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配 - 一旦匹配到某一个
catch,会进到catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(无finally)继续执行后面的代码
throws 异常类型
- 语法
public void 方法名() throws 异常类型1, 异常类型2 {
// ...
}
- 说明
throws 异常类型1, 异常类型2...指明此方法执行时,可能抛出的异常类型。- 一旦方法体的某一行出现异常,仍会在这一行生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后面的代码,将不再执行!
开发中如何选择异常的处理方式
方法重写的关于抛出异常的规则:子类重写的方法抛出的异常不大于父类被重写的方法抛出的异常
- 如果父类被重写的方法没有抛出异常,则子类重写父类的方法也不能抛出异常,子类中有异常必须要
try-catch - 如果多个方法(a, b, c)都有异常,并且在另一个方法(d)中调用这些方法(a的返回结果被b用到了,b的返回结果被c用到了),可以(a, b, c)都
throws, 然后在d方法中整体对a,b,c进行try-catch。
手动生成异常对象,并抛出(throw)
class Demo {
private Double radius;
public int compareTo(Object obj) throws Exception { // 0相等,1比传进来的大,-1比传进来的小
if (this == obj) return 0;
if (!(obj instanceof Demo)) throw new Exception("传入的数据类型不正确!");
Demo demo = (Demo)obj;
return this.getRadius().compareTo(demo.getRadius());
}
}
用户自定义异常类
class MyException extends Exception {
static final long serialVersionUID = -703489564654659L;
public MyException() {}
public MyException(String msg) {
super(msg);
}
}