异常基础知识

异常

笔记总结参考于黑马程序员 Java基础进阶篇(异常)

父类:Throwable

子类:Error

Error类描述的是在运行过程中非常严重且不可以处理的错误。

如:常见的两种严重错误

//例1
public class Test {
    public static void main(String[] args) {
        while (true){
            arrayList.add("abc");
        }
    }
}
/*报错信息:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space  即内存溢出的严重错误*/  

//例2
public class Test {
    public static void main(String[] args) {
        show();
    }
    public static void show(){
        show();
    }
}
/*报错信息:Exception in thread "main" java.lang.StackOverflowError 栈内存溢出的严重错误*/

子类:Exception

在这里插入图片描述

Exception类描述出现一些简单的且可以处理的错误。且分为两类:编译期异常运行期异常

图示

编译期异常(语法错误不算在内)

Exception的儿子(非RuntimeException):书写代码还没运行的时候就开始报错,如果这种异常存在时无法生成class文件的

看代码中两个例子:

public class Test {
    public static void main(String[] args) {
            String time = "1991-01-02";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date prase = simpleDateFormat.parse(time); //这里有编译错误,但Typora没显示 
        System.out.println(prase);
    }
}
//抛出异常 throws ParseException
public class Test throws ParseException {
    public static void main(String[] args) {
            String time = "1991-01-02";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date prase = simpleDateFormat.parse(time); //这就没问题了
        System.out.println(prase);
    }
}

/*同理,IO流也是有编译期异常的*/
FileInputStream fis = new FileInputStream("abc.txt");//FileNotFoundException
运行期异常

RuntimeException以及他的儿子:书写代码的过程中,是不会报错的,可以编译出class文件,可以运行,但是运行的时候报错

看代码中两个例子:

// 例1
public class Test {
public static void main(String[] args) throws ParseException {
         String s = null;
    	// null 怎么可以掉对象呢 但是不报错 运行的时候才报错
         boolean equals = s.equals("");
        System.out.println(equals);
    }
}
/*报错信息:Exception in thread "main" java.lang.NullPointerException 空指针异常*/

// 例2
public class Test {
    public static void main(String[] args) throws ParseException {
        int[] arr = {1,2,3};
        System.out.println(arr[100]);
    }
}
/*报错信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100 数组索引越界异常*/
为什么要分开编译期和运行期异常呢

编译期异常的设计理念:在程序员写代码的时候,有一些地方容易出错,且程序员都经常不注意,所以Java设计编译期异常,引起程序员注意。

throws处理方式:Java程序员了解到这个地方容易出错,就检查了一遍,请求jvm让代码编译通过。

public class Test throws ParseException {
    public static void main(String[] args) {
        String time = "1991-01-02";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date prase = simpleDateFormat.parse(time);
        System.out.println(prase);
    }
}

try-catch 处理方式:throws只起到一个“提示虚拟机”的作用,如果没检查好,以后运行的时候依然会报错。

举例某个场景:我们在编译期的时候检查不出来,后续是否报错的。因为有可能以后的程序员运行起来,用户输入一些错误。

public class Test{
    public static void main(String[] args) {
     Scanner sc = new Scanner();
     String pattern = sc.next();
     String str = "2018-09-23";
     SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try{
            Data d = sdf.parse(str);
        }catch(Exception e){
            System.out.println("请输入正确的格式");
        }
    }
}

运行期异常的设计理念:这些是给用于去准备的,比如1/0操作,,当出现问题的时候,不至于程序崩溃,而是可以继续执行问题代码以下的程序;

只用try-catch 处理方式,不用throws方式,因为没效果;

int i = 1/0;
System.out.println(i);//会报错

java是如何默认处理异常的

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
	at 刘东生.practice.Test.main(Test.java:12)
	
//异常的类型:ArrayIndexOutOfBoundsException  一般通过异常类型可以知道那里犯错
//异常的原因 100 
// 异常出现的位置:Test.java:12
    
// 报错之后 程序立刻终止

既然我们知道程序出现异常会中止程序,那如果程序中一段代码出现异常,但是我仍想执行下面代码的内容,如果执行,这就需要try-catch去处理异常了

try-catch 处理异常

格式

try{
    //可能出现问题的代码
}catch(Exception e){
    //处理异常
}

比如 处理上面那段索引越界的代码

注意:catch(//这里头写的代码可以是父类Exception),但是括号里头不能写其他类的比如NullPointerException e 异常,否则捕捉不到(所以为了避免捕捉不到异常,直接写Exception即可); 同时注意e.printStackTrace(); 这段代码,这样写可以知道异常报错的信息;如果第一个异常被捕捉到了,接下来的异常如例子中下面的空指针异常是不会被捕捉的。

public class Test {
    public static void main(String[] args) throws ParseException {
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[100]);
            
            String s = null;
            boolean equals = s.equals("");
            System.out.println(equals);
        } catch (ArrayIndexOutOfBoundsException e) {  //相当于 new ArrayIndexOutOfBoundsException();
            e.printStackTrace();  // 一般都这样写,这样写的话可以知道异常报错的信息
        }
        System.out.println(10000);
        System.out.println(10000);
        System.out.println(10000);
    }
}

/*输出内容:java.lang.ArrayIndexOutOfBoundsException: 100
	at 刘东生.practice.Test.main(Test.java:13)
10000
10000
10000 */

假如我想获取导致异常的原因是啥如何做呢?这里就用到了e.getMessage()方法

public class Test {
    public static void main(String[] args) throws ParseException {
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[100]);
        } catch (ArrayIndexOutOfBoundsException e) { 
           String message = e.getMessage();
        	System.out.println(message);
        }
        System.out.println(10000);
        System.out.println(10000);
        System.out.println(10000);
    }
}

/*输出内容:100
10000
10000
10000 */

源码分析

public Throwable{
public Throwable(String message) {
        detailMessage = message; //这里赋值
	}
 public String getMessage() {
        return detailMessage;
	}
}
//构造 new ArrayIndexOutOfBoundsException()对象出来
// e.getMessage(); --> "100"
Class ArrayIndexOutOfBoundsException extends Throwable{
    public ArrayIndexOutOfBoundsException(String s){
        super(s);
    }
}

自定义一个异常场景

比如:程序中不允许出现年龄为负数,如果年龄为负数,就需要报错一个异常。

底层代码:

public class Students {
    private int  age;
    public Students(){}
    public void setAge(int age) {
        if(age<0){
            throw new AgeOutOfBoundsException(age+"");
        }
        this.age = age;
    }
}
//自定义异常
public class AgeOutOfBoundsException extends RuntimeException{
    public AgeOutOfBoundsException(){}
    public AgeOutOfBoundsException(String message) {
            super(message);
    }
}

程序员写逻辑时候的代码:

public class test {
    public static void main(String[] args) {
        Students students = new Students();
        students.setAge(-10);
    }
}
//运行结果显示
/*Exception in thread "main" Test.AgeOutOfBoundsException: -10
	at Test.Students.setAge(Students.java:8)
	at Test.test.main(test.java:6)*/

这里再文字解释以下 -10 如何得到的。首先-10 先回传到setAge 方法中,然后经过这个 if(age<0){throw new AgeOutOfBoundsException(age+"");} 判断方法 ,将 -10 转换为字符串 “-10” 传给AgeOutOfBoundsException() 方法,AgeOutOfBoundsException() 方法通过有参构造方法中的super(message) 经过父类RuntimeException ,一直传到最后的Throwable()方法,这个最终父类方法有两个 Throwable(String message)getMessage()上面源码分析可以知道),将导致异常的信息返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值