14.从零开始学习Java-异常处理

转载请标明原文地址,后续会持续更新《从零开始学习》系列,数据结构和算法,Mysql和ssm框架。
如果有问题可以私信或者直接在文章下评论,大概晚上会回。
如果零基础的同学没有学习的大概方向也可以私信问我,发给你一些学习路线和一些B站的学习视频地址。
希望能为世界带来些微价值,peace!
异常

一、异常的概念

概念:程序在运行过程中出现的特殊情况。

二、异常的分类

Throwable:可抛出的,一切错误或异常的父类,位于java.lang包中。

在这里插入图片描述

-Error:JVM、硬件、执行逻辑错误,不能手动处理。

-Exception:程序在运行和配置中产生的问题,可处理。

​ -RuntimeException:运行中异常,可处理,可不处理。

​ -CheckedException:受查异常,必须处理。//在Exception中除了RuntimeException的所有子类都属于CheckedException。//在编译时会报错,必须处理。

//RuntimeException异常
public class TestRuntimeException {

	public static void main(String[] args) {
		m6();
	}
	
	//java.lang.NullPointerException//空指针异常
	public static void m1(){
		Object o = null;
		
		o.hashCode();
	}
	
	//java.lang.ArrayIndexOutOfBoundsException//数组下标越界异常
	public static void m2(){
		int[] nums = new int[4];
		
		System.out.println(nums[5]);
	}
	
	//java.lang.StringIndexOutOfBoundsException
	public static void m3(){
		String str = "abc";
		
		System.out.println(str.charAt(5));
	}
	
	//java.lang.ArithmeticException//除数不能为0
	public static void m4(){
		System.out.println(3/0);
	}

	//java.lang.ClassCastException//类转换异常
	public static void m5(){
		Object o = new Integer(123);
		Scanner input = (Scanner)o;
	}
	
	//java.lang.NumberFormatException//数字格式异常
	public static void m6(){
		new Integer("10a");
	}
}

三、异常的产生//告诉有异常。

  • 自动抛出异常:当程序在运行时遇到不符合规范的代码或结果时,会产生异常。

  • 手动抛出异常:

    语法:

    throw new 异常类型(“实际参数”);

  • 产生异常结果:相当于遇到return语句,导致程序因异常而终止。//除非有finaly,否则后面的语句不再执行。

//1、
RuntimeException e = new RuntimeException();//此刻仅仅是个普通对象
throw e;
//2、
//throw new RuntimeException();

public class TestThrowException {

	public static void main(String[] args) {
		Student s = new Student();
		s.setAge(300);	
		System.out.println(s.getAge());	
	}
}


class Student{
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		if(age > 0 && age <253){
			this.age = age;
		}else{
			RuntimeException e = new RuntimeException();//此刻仅仅是个普通对象//1、
			throw e;
			//throw new RuntimeException();//2、
		}
	}	
	
}

四、异常的传递

  • 异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)。//JVM默认异常处理为打印堆栈跟踪信息。
  • 受查异常:throws 声明异常,修饰在方法参数列表后端。
  • 运行时异常:因可处理可不处理,无需声明异常。
public class TestTrasnferException {

    public static void main(String[] args) {//m3、m2都没处理,默认处理异常(打印堆栈跟踪信息)
        System.out.println("main - start");
        try {
            m1(2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("main - end");

        //method(1);
    }

    public static void m1(int n) throws Exception {
        System.out.println("m1 - start");
        m2(n);
        System.out.println("m1 - end");
    }

    public static void m2(int n) throws Exception {
        System.out.println("m2 - start");
        m3(n);
        System.out.println("m2 - end");
    }

    public static void m3(int n) throws Exception {//向上报告(告知了调用者,此方法可能产生的异常)
        System.out.println("m3 - start");
        if (n % 2 == 0) {
            throw new Exception("打印菱形,行号必须为奇数!");//相当于遇到return语句,导致程序因异常而终止。后面的语句不再执行。
        }
        System.out.println("打印菱形");
    }
}

五、异常的处理//干掉异常。

try{

//可能出现异常的代码

}catch{

//异常处理的相关代码,如:getMessage()、printStackTrace()

}finally{

//无论是否出现异常,都需执行的代码结构,常用于释放资源。

}

注意:

try…catch覆盖的范围

另外多重catch需要从小到大,父类类型写到最后。//没有直接继承关系时,catch的位置无所谓。

//我感觉每个程序都可以写一个try{}catch(Exception e){};

public class TestTryCatch {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        System.out.println("请输入被除数:");
        int num1 = input.nextInt();

        System.out.println("请输入除数:");
        int num2 = input.nextInt();
        
        try{
            int result = num1 / num2; //throw new ArithmericException("/ by zero")
            System.out.println(result);
        }catch(Exception e){//= new ArithmeticException();
            //System.out.println("注意,除数不能为零!");//处理方案1(自定义处理)
            //e.printStackTrace();//处理方案2(打印堆栈跟踪信息)
            //System.out.println(e.getMessage());//处理方案3(单独获取Message作为异常原因)
        }

        System.out.println("程序结束");//遇到异常也会打印。

    }
}
输出:
请输入被除数:
3
请输入除数:
0
程序结束
public class TestMoreTryCatch {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int result = -1;
        try{

            System.out.println("请输入被除数:");
            int num1 = input.nextInt();

            System.out.println("请输入除数:");
            int num2 = input.nextInt();

            result = num1 / num2;

        }catch(ArithmeticException e){
            System.out.println("除数不能为零!");
        }catch(InputMismatchException e){
            System.out.println("请输入有效整数!");
        }catch(RuntimeException e){
            System.out.println("未知的运行时异常,请联系管理员");
        }catch(Exception e){
            System.out.println("未知的受查异常,请联系管理员!");
        }

        System.out.println(result);//无论运行是否存在异常,都要打印结果
        System.out.println("程序结束");//会输出
输出结果:
请输入被除数:
3
请输入除数:
0
除数不能为零!
-1
程序结束

六、自定义异常

  • 需继承自Exception或Exception的子类,常用RuntimeException。
  • 必要提供的构造方法:
    • 无参构造方法
    • String message参数的构造方法
public class TestDefinedException {
    public static void main(String[] args){
        Student student = new Student();
        try {
            student.setAge(1112);
        } catch (AgeException e) {
            e.printStackTrace();
        }
        try {
            student.setSex("aaaa");
        } catch (Exception e) {
            System.err.println("性别输出有误");//转换为带红色的输出
        }
    }
}

//受查异常
class AgeException extends Exception{
    public AgeException() {
    }

    public AgeException(String message) {
        super(message);
    }
}

//运行时异常
class SexMismatchException extends RuntimeException{
    public SexMismatchException() {
    }

    public SexMismatchException(String message) {
        super(message);
    }
}

class Student{
    private  int age;
    private  String sex;

    public int getAge() {
        return age;
    }

    public void setAge(int age) throws AgeException {//可以为Exception,但是和抛出的异常一样为最好
        if (age>0&&age<254){
            this.age = age;
        }else{
            //抛异常
            throw new AgeException("年龄的正确区间为1到253");//AgeException
        }
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) throws SexMismatchException{
        if (sex.equals("男")||sex.equals('女')){
            this.sex = sex;
        }else{
            //抛异常
            throw  new SexMismatchException("性别为男或女");
        }
    }
}

七、方法覆盖

带有异常声明的方法覆盖:

  • 方法名、参数列表、返回值类型必须和父类形同。
  • 子类的访问修饰符合父类形同或是比父类更宽。
  • 子类中的方法,不能抛出比父类或接口更宽泛的异常。
public class TestOverrideExceptionMethod {

	public static void main(String[] args) {
		Super s = new Sub();		
		//s.method();
		
		Printable p = new MyClass();
		
		try {
			p.print();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		MyClass mc = new MyClass();
		
		try {
			mc.print();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
}

class Super{
	public void method() throws Exception{
		System.out.println("Super - method()");
	}	
}

class Sub extends Super{
	public void method() throws IOException , ClassNotFoundException, RuntimeException{//子类可以有多个异常,但是不能抛出比父类或接口更宽泛的异常。
		System.out.println("Sub - method()");
	}
}

interface Printable{
	public void print() throws IOException;
}

class MyClass implements Printable{
	@Override
	public void print() throws IOException{
	}	
}

八、jvm储存区域,栈的解析

//栈帧结构

public class TestReturn {
    public static void main(String[] args){
        int result = m1();
      System.out.println(result);
    }
    public static int m1(){
        int a = 10;
        try {
            a = 20;
            throw  new  RuntimeException();
        }catch (Exception e){
            a = 30;
            return  a;//return执行了两次,执行完finally后返回执行return返回30。
        }finally {
            a = 40;

        }
    }
}
//输出:30

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值