1.异常
在开发中,除 语法 和 逻辑错误 外,导致的不正常的情况称为“异常”;
可分为两类:
Error:Java 虚拟机无法解决的严重问题,一般不通过编写代码处理;
Exception:因编程错误或偶然的外在因素导致的一般性问题,可以通过代码处理;
”异常“主要讲的是”Exception“ 可以通过代码处理的这种情况;
1.1 解决办法
遇到错误有两种解决办法:
一. 遇到错误停止程序的运行;
二. 在编写程序时,”预判“可能会出现的错误并对错误做出处理;
1.2 分类
可以通过代码处理的”异常“又可分为:
编译时异常(受检异常);
运行时异常(非受检异常);
import org.junit.Test;
import java.util.Date;
import java.util.Scanner;
/**
* 出现的异常:
* java.lang.Throwable
* |------java.long.Error:一般不编写针对性的代码进行处理。
* |------java.long.Exception:可以进行异常处理。
* |-----编译时异常(checked)
* |-----IOException
* |-----FileNotException
* |-----ClassNotFoundException
* |-----运行时异常(unchecked)
* |-----NullPointerException:空指针异常
* |-----ArrayIndexOutOfBoundException:数组角标越界
* |-----ClassCastException:类型转换异常
* |-----NumberFormatException:数字格式异常
* |-----InputMismatchException:数据输入异常
* |-----ArithmeticException:算数异常
*/
public class Main {
//运行时异常:只有运行才能看到错误
//NullPointerException:空指针异常
@Test
public void test1(){
int [] arr = null;
System.out.println(arr[3]);
}
//ArrayIndexOutOfBoundException:数组角标越界
@Test
public void test2(){
int [] arr1 = new int[6];
System.out.println(arr1[6]);
}
//ClassCastException:类型转换异常
@Test
public void test3(){
Object object = new Date();
String str = (String) object;
}
//NumberFormatException:数字格式异常
@Test
public void test4(){
String s = "a123bc";
Integer integer = Integer.parseInt(s);
}
//InputMismatchException:数据输入异常
@Test
public void test5(){
Scanner scn = new Scanner(System.in);//输入非数字型的会出现该异常
int score = scn.nextInt();
System.out.println(score);
}
//ArithmeticException:算数异常
@Test
public void test6(){
int a = 10;
int b = 0;
System.out.println(a / b);
}
//编译时异常
}
2. 异常处理
将异常处理的代码集中在一起,与正常的代码分开,使得程序简洁,优雅,便于维护;
异常的处理:抓抛模型
过程一:“抛”
程序在执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出;
一旦抛出对象后,其后的代码不再执行;
过程二:“抓”:即 异常的处理方式:
2.1 异常处理机制一:try-catch-finally
1.catch 中的异常类型如果没有子父类关系,参数列表的异常类型顺序无所谓
若存在子父类关系,则要求子类一定声明在父类上面
2.常用的异常对象处理方式:
printStackTrace():最常用;
getMessage():返回字符串;
import org.junit.Test;
import java.util.InputMismatchException;
/**
* 异常的处理:抓抛模型
*
* 过程一:“抛”
* 程序在执行过程中,一旦出现异常,就会在异常代码处生成一个
* 对应异常类的对象,并将此对象抛出;
* 一旦抛出对象后,其后的代码不再执行;
*
* 过程二:“抓”:
* 即 异常的处理方式:
* 1.try-catch-finally;
* try{
* 可能出现异常的代码
* }catch(异常类型 1 变量名 1){
* 处理异常的方式 1
* }catch(异常类型 2 变量名 2){
* * 处理异常的方式 2
* }......
* finally {
* 一定会执行的代码
* }
*
* 1.catch 中的异常类型如果没有子父类关系,参数列表的异常类型顺序无所谓
* 若存在子父类关系,则要求子类一定声明在父类上面
* 2.常用的异常对象处理方式:
* printStackTrace():最常用
* getMessage():返回字符串
*
* 2.throws
*
*/
public class DealException {
//NumberFormatException:数字格式异常
@Test
public void test(){
String s = "a123bc";
try {
//该句可能有异常,用 try 包起来
Integer integer = Integer.parseInt(s);
System.out.println("该句执行吗?");
}catch (NumberFormatException n){
// System.out.println("亲,数字格式异常啦");
n.printStackTrace();
}catch (InputMismatchException i){
// System.out.println("思密达,输入异常啊");
i.getMessage();
}catch (ArithmeticException a){
System.out.println("前轱辘不转后轱辘转,算数异常啊");
}
System.out.println("执行完毕了!");
/**
* 执行过程:
* 1.38 行可能出现异常,因此需要使用 try 包起来,
* 2.若出现异常,该行之后的代码不再执行
* 并自动生成一个对应异常类型的对象,
* 随之根据 catch 的形参类型匹配其处理方式,
* 一旦处理完成,就会跳出 try-catch 结构,
* 继续处理接下来的代码;
* 3.若无法匹配到该异常类型的处理方式,
* 则还会出现异常,并停止代码运行,与没有处理无异;
*/
}
}
2.2 异常处理机制二:throws
“throws + 异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型;
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,
此对象满足 throws 后的异常类型时,就会被抛出。
异常代码后续的代码,就不再执行!
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 异常的处理方式二:throws + 异常类型
* 1."throws + 异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型;
* 一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象
* 满足 throws 后的异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
*
* 2.体会:try-catch-finally:真正将异常处理掉了;
* throws:只是将异常抛给了方法的调用者,并没有将异常处理掉;
*
*/
public class ExceptionTest2 {
public static void main(String[] args) {
try{
method2();
}catch (IOException e) {
e.printStackTrace();
}
}
public static void method2() throws IOException{
method1();
}
public static void method1() throws FileNotFoundException,IOException {
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
System.out.println("哇哈哈哈哈哈哈!");
}
}
2.3 对比
try-catch-finally:真正将异常处理掉了;
throws:只是将异常抛给了方法的调用者,并没有将异常处理掉;
3. 开发常用
开发中选择使用 try-catch-finally 还是 throws:
3.1 如果父类重写的方法没有使用 throws方式处理异常,子类重写的方法也不能使用 throws,即如果子类重写的方法有异常,必须使用 try-catch-finally 处理;
3.2 执行的方法 a 中,先后调用了另外的几个方法。这几个方法是递进关系执行的,
建议这几个方法使用 throws 处理,而执行的方法 a 使用 try-catch-finally 处理,
4. 手动抛出异常
下面是”年龄输出“的代码实例;
1. 在 Student 类中的 show()方法中使用 throw 生成一个异常对象;
2. 在 show( ) 方法的声明处使用 throws 进行异常处理:将异常抛给类的调用者;
3. 类的调用者使用 try-catch-finally 处理异常;
public class ArtiException {
public static void main(String[] args) {
try{
Student s = new Student();
s.show(-2000);
System.out.println(s);
}catch(Exception e){
// e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
class Student{
private int age;
public void show(int age) throws Exception {//在方法的声明处进行异常处理:不负责,甩锅式的处理
if(age > 0){
this.age = age;
}else {
// System.out.println("您输入的数据有误");
// 手动抛出异常
//运行时异常,会报错,可以不处理
// throw new RuntimeException("您输入的数据有误!");
throw new Exception("您输入的数据有误的啦!");//方法内生成一个异常对象
}
}
}
除上面所述,还有”用户自定义异常类“相关的知识,但不常用。