JAVASE异常部分

《动力节点视频学习过程中的笔记》

一、 异常

1.什么是异常?异常的作用?

异常以类和对象的形式存在,每一个异常类都可以new一个异常对象。
Exception in thread “main” java.lang.ArithmeticException: / by zero
at Exception01.ExceptionTest01.main(ExceptionTest01.java:7)
JVM将new的异常对象打印输出控制台,增强程序健壮性。

2.异常的继承结构?

用UML图来画继承结构,

UML?
一种统一建模语言,一种图标式语言,只要是面向对象的编程语言,都有UML。一般是软件设计人员使用,画系统架构图。
UML图中描述类和类之间的关系,程序执行的流程,对象的状态等。
画UML图有很多工具,例如:Rational Rose(收费的)、starUML等…
在这里插入图片描述

3.异常的分类?

编译时异常(受检异常/受控异常)一般发生的概率比较高,在运行之前要对其进行预处理。
运行时异常(RuntimeException)(未检异常/非受控异常)一般发生的概率比较低。

4.异常的处理

/**doSome方法声明时使用了throws ClassNotFoundException,该异常属于编译时异常,
 *调用时必须预处理
 **/
public class ExceptionTest01 {
    public static void main(String[] args)  {
        doSome();//这里报错
    }
    public static void doSome()throws ClassNotFoundException{
        System.out.println("hi");
    }
}

(1)【异常上抛】在方法声明的位置上,使用throws 关键字,抛给上一级。谁调用我,我就抛给谁。
JAVA中异常发生后如果一直上抛,最终抛给了main方法,main方法继续上抛,抛给JVM,VM知道这个异常发生,只有一个结果。终止java程序的执行。

(2)【异常捕捉】使用try catch语句进行异常的捕捉。
① 语法格式
try {//以上代码出现错误,直接进行catch语句块
}catch (异常名 变量名){
}
异常捕捉之后,后续代码继续执行。
②catch写多个时,从上到下必须遵循从小到大。
③catch后面可以写具体的异常类型,也可以写该异常的父类。

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ExceptionTest01 {
    // 一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM。JVM只有终止。
    // 异常处理机制的作用就是增强程序的健壮性。怎么能做到,异常发生了也不影响程序的执行。所以
    // 一般main方法中的异常建议使用try..catch进行捕捉。main就不要继续上抛了。
    /*
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("main begin");
        m1();
        System.out.println("main over");
    }
     */
    public static void main(String[] args) {

        // 100 / 0这是算术异常,这个异常是运行时异常,你在编译阶段,可以处理,也可以不处理。编译器不管。
        //System.out.println(100 / 0); // 不处理编译器也不管
        // 你处理也可以。
        /*
        try {
            System.out.println(100 / 0);
        } catch(ArithmeticException e){
            System.out.println("算术异常了!!!!");
        }
         */

        System.out.println("main begin");
        try {
            // try尝试
            m1();
            // 以上代码出现异常,直接进入catch语句块中执行。
            System.out.println("hello world!");
        } catch (FileNotFoundException e){ // catch后面的好像一个方法的形参。
            // 这个分支中可以使用e引用,e引用保存的内存地址是那个new出来异常对象的内存地址。
            // catch是捕捉异常之后走的分支。
            // 在catch分支中干什么?处理异常。
            System.out.println("文件不存在,可能路径错误,也可能该文件被删除了!");
            System.out.println(e); //java.io.FileNotFoundException: D:\course\01-课\学习方法.txt (系统找不到指定的路径。)
        }

        // try..catch把异常抓住之后,这里的代码会继续执行。
        System.out.println("main over");
    }

    private static void m1() throws FileNotFoundException {
        System.out.println("m1 begin");
        m2();
        // 以上代码出异常,这里是无法执行的。
        System.out.println("m1 over");
    }

    // 抛别的不行,抛ClassCastException说明你还是没有对FileNotFoundException进行处理
    //private static void m2() throws ClassCastException{
    // 抛FileNotFoundException的父对象IOException,这样是可以的。因为IOException包括FileNotFoundException
    //private static void m2() throws IOException {
    // 这样也可以,因为Exception包括所有的异常。
    //private static void m2() throws Exception{
    // throws后面也可以写多个异常,可以使用逗号隔开。
    //private static void m2() throws ClassCastException, FileNotFoundException{
    private static void m2() throws FileNotFoundException {
        System.out.println("m2 begin");
        // 编译器报错原因是:m3()方法声明位置上有:throws FileNotFoundException
        // 我们在这里调用m3()没有对异常进行预处理,所以编译报错。
        // m3();

        m3();
        // 以上如果出现异常,这里是无法执行的!
        System.out.println("m2 over");
    }

    private static void m3() throws FileNotFoundException {
        // 调用SUN jdk中某个类的构造方法。
        // 这个类还没有接触过,后期IO流的时候就知道了。
        // 我们只是借助这个类学习一下异常处理机制。
        // 创建一个输入流对象,该流指向一个文件。
        /*
        编译报错的原因是什么?
            第一:这里调用了一个构造方法:FileInputStream(String name)
            第二:这个构造方法的声明位置上有:throws FileNotFoundException
            第三:通过类的继承结构看到:FileNotFoundException父类是IOException,IOException的父类是Exception,
            最终得知,FileNotFoundException是编译时异常。

            错误原因?编译时异常要求程序员编写程序阶段必须对它进行处理,不处理编译器就报错。
         */
        //new FileInputStream("D:\\course\\01-开课\\学习方法.txt");

        // 我们采用第一种处理方式:在方法声明的位置上使用throws继续上抛。
        // 一个方法体当中的代码出现异常之后,如果上报的话,此方法结束。
        new FileInputStream("D:\\course\\01-课\\学习方法.txt");

        System.out.println("如果以上代码出异常,这里会执行吗??????????????????不会!!!");
    }
}

5.异常的方法

(1)String msg = exception.getMessage();

(2)exception.printStackTrace();异常追踪信息从上往下看,sun公司写的就不看了,主要看自己写的。

public class ExceptionTest02 {
    public static void main(String[] args) {
        NullPointerException e = new NullPointerException("空指针异常");
        String str = e.getMessage();//获取new异常时传入的字符串
        System.out.println(str);
        e.printStackTrace();//打印异常堆栈追踪信息
    }
}

执行结果:

空指针异常
java.lang.NullPointerException: 空指针异常
	at Exception01.ExceptionTest02.main(ExceptionTest02.java:6)

6.finally关键字

(1)finally子句:与try、catch一起出现,(可以没有catch,必须有try)最后执行,并且一定会执行,即使try语句块中的代码出现了异常。
(2)finally语句块中一般用来中完成资源的释放/关闭。
(3)以下代码的执行顺序:
try
finally
return
若在finally后面加一条语句,该语句不会执行。

        try {
            System.out.println("!!");
            return;
        }finally{
            System.out.println("~~");
        }

(4)方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!)
return语句一旦执行,整个方法必须结束(亘古不变的语法!)

public class ExceptionTest13 {
    public static void main(String[] args) {
        int result = m();
        System.out.println(result); //100
    }
    public static int m(){
        int i = 100;
        try {
            // 这行代码出现在int i = 100;的下面,所以最终结果必须是返回100
            // return语句还必须保证是最后执行的。一旦执行,整个方法结束。
            return i;
        } finally {
            i++;
        }
    }
}//结果是100.不是101

反编译之后的效果:


public static int m(){
    int i = 100;
    int j = i;
    i++;
    return j;
}

7.final、finally、finalize

(1)final是关键字,表示不可改变的。
(2)finally是关键字,与try联合使用。
(3)finalize是Object类里的一个方法,是标识符。

8.自定义异常

(1)写一个异常class继承Exception/RunTimeException。
(2)写两个构造方法,一个无参,一个有参。

    class MyException extends Exception{
        public MyException(){
            
        }
        public MyException(String s){
            super(s);
        }
    }

有什么作用?

throw new MyException()//手动抛出异常

import java.util.Scanner;

public class ExceptionTest03 {
    public static void main(String[] args) {
        System.out.println("请输入用户名:");
        Scanner a = new Scanner(System.in);
        String str1 = a.next();
        System.out.println("密码:");
        Scanner b = new Scanner(System.in);
        String str2 = b.next();
        UserService user = new UserService();
        try {
            user.register(str1, str2);
        }catch (MyException e) {
            System.out.println(e.getMessage());
        }
    }
}

class MyException extends Exception{
    public MyException(){

    }
    public MyException(String s){
        super(s);
    }
}
public class UserService {
        private String username;
        private String password;

        public void register(String username, String password) throws MyException {
            /*
              if (username.length() >= 6 && username.length() <= 14) {
                this.username = username;
                this.password = password;
            } else {
                throw new MyException("用户名不合法");
            }
             */
            if (username==null||username.length()<6||username.length()>14){
                throw new MyException("用户名不合法,长度必须在6-14之间");
            }//引用==null的判断最好放在所有条件最前边,放在后边容易出现空指针异常
              //写成null==username更好
            System.out.println("注册成功!");
        }

}

9.方法覆盖时异常相关

重写之后的方法不能比重写之前抛出更多的异常,可以更少。父类不抛,子类不能抛。(RunTImeException可以抛)父类抛了,子类可以不抛,可以抛一样的,可以抛比他小的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值