目录

  • 一、异常
  • 1.1 概念
  • 1.2 异常的必要性
  • 二、异常分类
  • 2.1 错误
  • 2.2 异常
  • 三、异常产生和传递
  • 3.1 异常产生
  • 3.2 异常传递(这个其实是在打印信息中显示)
  • 四、异常处理【重点】
  • 4.1 try...catch...
  • 4.2 try...catch...finally...
  • 4.3 多重catch
  • 4.4 try…finally...
  • 4.5 小结
  • 五、声明、抛出异常
  • 5.1 声明异常 在方法上用 throws
  • 5.2 抛出异常(在代码中用 throw new )
  • 六、自定义异常
  • 6.1 编写自定义异常
  • 6.2 异常中方法覆盖


一、异常

1.1 概念

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

1.2 异常的必要性

任何程序都可能存在大量的未知问题、错误。

如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。

二、异常分类


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

2.1 错误

  • Error: JVM、硬件、执行逻辑错误,不能手动处理。
  • 常见错误: StackOverflowError、 OutOfMemoryError等。
  • 你的游戏8G内存 : 2G
  • StackOverflowError : 如果是由于逻辑代码问题,需要改正,比如死循环

2.2 异常

  • Exception:程序在运行和配置中产生的问题,可处理。
  • RuntimeException:运行时异常,可处理,可不处理。
  • CheckedException:检查时异常,必须处理。

常见运行时异常:

异常

描述

NullPointerException

空指针异常

ArrayIndexOutOfBoundsException

数组越界异常

ClassCastException

类型转换异常

NumberFormatException

数字格式化异常

ArithmeticException

算术异常

案例演示:

package com.qfedu.test01;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

//1.异常
    //1. Error  错误,不可修正  内存溢出, 堆溢出
    //2. 代码逻辑报错是:  Exception   程序运行期间

//Exception   抛出异常
// NullPointerException 空指针异常    没有初始化对象(Null) ==》 这种情况你去调方法和属性
// ArrayIndexOutOfBoundsException 数组下标越界
// ClassCastException  类转换异常
//NumberFormatException  数据格式异常
// ArithmeticException 算术异常
public class Test01 {
    public static void main(String[] args) {

        String str = null;
        //int length = str.length();

        int[] a = new  int[9]; // index 0-8
        //a[9] = 10;

        Object o = "444";
        //Integer i  = (Integer)o;

        // TreeSet 实现排序, 里边的对象,实现Comparable    重写compareTo
        Set<Test01> s = new TreeSet<>();
       // s.add(new Test01());

        String str1 ="1+我";
        //Integer integer = Integer.valueOf(str1);
        //System.out.println(integer);

        System.out.println(1/0);
    }
}

三、异常产生和传递

3.1 异常产生

  • 自动抛出异常:当程序在运行时遇到不符合规范的代码或结果时,会产生异常。
  • 手动抛出异常:语法:throw new 异常类型(“实际参数”)。
  • 产生异常结果:相当于遇到 return语句,导致程序因异常而终止。

3.2 异常传递(这个其实是在打印信息中显示)

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

案例演示:异常的产生、传递

/**
 * 演示异常的产生和传递
 * 要求:输入两个数字实现两个数字相除
 */
public class TestException1 {
	public static void main(String[] args) {
		operation();
	}
	public static void operation() {
		System.out.println("---opration-----");
		divide();
	}
	public static void divide() {
		Scanner input=new Scanner(System.in);
		System.out.println("请输入第一个数字");
		int num1=input.nextInt();//出现异常,没有处理,程序中断
		System.out.println("请输入第二个数字");
		int num2=input.nextInt();
		int result=num1/num2;//出现异常没有处理,所以程序中断
		System.out.println("结果:"+result);
		System.out.println("程序执行完毕了...");
	}
}

四、异常处理【重点】

Java的异常处理是通过5个关键字来实现的:

  • try:执行可能产生异常的代码 。
  • catch:捕获异常 ,并处理。
  • finally:无论是否发生异常,代码总能执行。
  • throw: 手动抛出异常 。
  • throws:声明方法可能要抛出的各种异常。

4.1 try…catch…

语法:

try {
	//可能出现异常的代码
} catch(Exception e) {
	//异常处理的相关代码,如:getMessage()、printStackTrace()
}

注:1、正常请求 2、出现异常并处理 3、异常类型不匹配

4.2 try…catch…finally…

语法:

```java
try {
	//可能出现异常的代码
} catch(Exception e) {
	//异常处理的相关代码,如:getMessage()、printStackTrace()
} finally{
	//是否发生异常都会执行,可以释放资源等。
}
package com.qfedu.exception;

import com.qfedu.Hero;

import java.lang.reflect.Method;

public class Test3 {

    public static void main(String[] args) {

        add();

    }

    public  static void add() {

        try{
            Class<?> aClass = Class.forName("hahaero");
            Hero o = (Hero) aClass.newInstance();

            o.add(1);

        } catch (ClassNotFoundException e) {
            //打印异常
            System.out.println("我发生异常了,ClassNotFoundException,我退出了。。");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally { //最终的意思
            //必要的操作是要完了,比如释放资源
            //连接数据库
            System.out.println("比如释放资源");
        }
    }
}

注:1、finally块是否发生异常都执行,释放资源等 2、finally块不执行的唯一情况,退出java虚拟机

4.3 多重catch

语法:

try{
	//可能出现异常的代码。
}catch(异常类型1){
	//满足异常类型1执行的相关代码。
}catch(异常类型2){
	//满足异常类型2执行的相关代码。
}catch(异常类型3){
	//满足异常类型3执行的相关代码
}
public class TestException4 {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int result=0;
		try {
//			String string=null;
//			System.out.println(string.equals("hello"));
			System.out.println("请输入第一个数字");
			int num1=input.nextInt();//InputMismatchException
			System.out.println("请输入第二个数字");
			int num2=input.nextInt();
			result=num1/num2;//发生异常// ArethmicException
		}catch (ArithmeticException e) {//捕获 Exception:是所有异常的父类	
			System.out.println("算术异常");
		}catch (InputMismatchException e) {
			System.out.println("输入不匹配异常");
		}catch (Exception e) {
			System.out.println("未知异常");
		}
		System.out.println("结果是:"+result);
		System.out.println("程序结束了...");
	}
}

注意:

4.4 try…finally…

  • try…finally…不能捕获异常 ,仅仅用来当发生异常时,用来释放资源。
  • 一般用在底层代码,只释放资源不做异常处理,把异常向上抛出。

语法:

try{
	//可能出现异常的代码
}finally{
	//是否发生异常都会执行,可以释放资源等
}
package com.qfedu.exception;

import com.qfedu.Hero;

import java.lang.reflect.Method;

public class Test4
{
    public static void main(String[] args) {

         int a = add("com.qfedu.Hero");

        System.out.println(a);
    }

    public static   int add(String type) {
        try {

            if(type  != null) {

                //进一步判断 type 是不com.qfedu
                if(type.startsWith("com.qfedu")) {

                    //1.发生异常
                    Class<?> aClass = Class.forName(type);

                    Hero o = (Hero) aClass.newInstance();
                    o.add(1);

                    System.out.println("3333333");
                    return 1;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            System.out.println("哈哈");
        }
        return 0;
    }
}

4.5 小结

  • try{ } catch{ }
  • try{ } catch{ } catch{ }
  • try{ } catch{ } finally{ }
  • try{ } catch{ } catch{ } finally{ }
  • try{ } finally{ }

注:多重catch,遵循从子( 小 )到父( 大 )的顺序,父类异常在最后

五、声明、抛出异常

5.1 声明异常 在方法上用 throws

如果在一个方法体中抛出了异常,如何通知调用者?

  • throws关键字:声明异常
package com.qfedu.exception;

import com.qfedu.Hero;

public class Test5 {

    public static void main(String[] args) {
        //try catch在上层方法里捕捉异常
        try {
            add("com.qfedu.Hero");
            System.out.println("aaaa");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    public static void add(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        //1.发生异常
        Class<?> aClass = Class.forName(type);

        Hero o = (Hero) aClass.newInstance();
        o.add(1);

        System.out.println("3333333");
    }
}

5.2 抛出异常(在代码中用 throw new )

除了系统自动抛出异常外,有些问题需要程序员自行抛出异常。

  • throw关键字:抛出异常
package com.qfedu.exception;

import java.util.Scanner;

public class Test6 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int i = scanner.nextInt();
        int j = scanner.nextInt();

        if(j==0) {
            throw new RuntimeException("除数不能为0");
        }
    }
}

六、自定义异常

6.1 编写自定义异常

  • 需继承Exception或Exception的子类,代表特定问题。
  • 异常类型名称望文生义,可在发生特定问题时抛出对应的异常。

常用构造方法:

  • 无参数构造方法。
  • String message参数的构造方法。
package com.qfedu.exception;

public class HeroException extends RuntimeException {

    public HeroException() {
    }

    //message 指的是错误信息
    public HeroException(String message) {
        super(message); //调用父类的有参构造器
    }
}
package com.qfedu.exception;

import java.util.Scanner;

public class Test6 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int i = scanner.nextInt();
        int j = scanner.nextInt();

        if(i==0) {
             // throw new RuntimeException
            throw new HeroException("i 不建议是0,否则 除的没有意义 ");
        }

        if(j==0) {
            throw new RuntimeException("除数不能为0");
        }
    }
}

6.2 异常中方法覆盖

带有异常声明的方法重写:

  • 子类中的方法抛出的异常 <= 父类检查时异常。
public class Animal {
	public void eat() throw Excetion{
		System.out.println("父类吃方法..........");
	}
}
public class Dog extends Animal{
	@Override
	public void eat() throw RuntimeException{ 
        //出现错误,父类没有声明异常,子类不能声明异常
		System.out.println("子类的吃的方法..........");
	}
}