java基础语法(二十)异常

1、什么是异常,java提供异常处理机制有什么用?
程序在执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
java把该异常信息打印输出到控制台,让程序员看到异常信息后可以对程序进行修改,让程序更加健壮。
2、java语言安装异常是以什么形式存在的呢
异常在java中以类的形式存在,每一个异常类都可以创建异常对象
3、异常的继承结构
Throwable 不管是错误还是异常都是可以抛出的。
Error 所有的错误只要发生,java程序只有一个结果那就是终止程序的执行。退出JVM,错误是不能处理的。
ExceptionSubClass Exception的直接子类 所有Exception的直接子类都叫做编译时异常。
编译时异常是表示必须在编写程序的时候预先对这种异常进行处理,如果不处理,编译器报错。
所有的RuntimeException及子类都属于运行时异常。运行时异常在程序编写阶段可以选择处理也可以选择不处理。

Object
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
Exception下有两个分支:
    Exception的直接子类:编译时异常
    RuntimeException:运行时异常

4、编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的
所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。异常的发生就是在new异常对象。
5、编译时异常和运行时异常
编译时异常一般发生的概率比较高
运行时异常一般发生的概率比较低
假设java中没有对异常划分,没有分为:编译时异常和运行时异常,
所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果?
首先,如果这样的话,程序肯定是绝对的安全。但是程序员编写程序太累,代码到处都是处理异常的代码。
编译时异常又叫做 受检异常 受控异常
运行时异常又叫做 未受检异常 非受控异常
7、java语言中对异常的处理包括两种方式:
第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。
第二种方式:使用try…catch语句进行异常的捕捉。
注意:java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,
JVM知道这个异常发生,只有一个结果,终止java程序的执行。

public class exceptionTest01 {
    public static void main(String[] args) {
        //通过"异常类"实例化"异常对象"
        NumberFormatException nfe = new NumberFormatException("数组格式化异常!");
        System.out.println(nfe);

        //main方法中调用doSome()方法
        //因为doSome()方法在声明的位置上有:throws ClassNotFoundException
        //在调用doSome()方法的时候必须对这种异常进行预先的处理,如果不处理,编译器就会报错
        //编译器报错信息:Unhandled exception: java.lang.ClassNotFoundException
        //代码报错的原因:doSome()方法在声明位置上使用了:throws ClassNotFoundException,
        //而ClassNotFoundException是编译时异常
        //doSome();
    }

    /**
     * doSome方法在声明的位置上使用了:throws ClassNotFoundException
     * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。
     * 叫做类没找到异常。这个异常的直接父类是:Exception,所以ClassNotFoundException属于编译时异常。
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!");
    }

}

处理异常的第一种方式:在方法声明的位置上使用throws关键字抛出,谁调用这个方法,就抛给谁。抛给调用者来处理。
注意:只要异常发生,采用上抛的方式,此方法的后续代码就不会执行。
另外注意,try语句块中的某一行出现异常,该行后面的代码不会执行。
try…catch捕捉异常之后,后续代码可以执行。
深入try…catch
1、catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
2、catch可以写多个。建议catch的时候,精确的一个一个处理,这样有利于程序的调试。
3、catch写多个的时候,从上到下,必须遵守从小到大。
处理编译时异常,应该上抛还是捕捉,怎么选?
如果希望调用者来处理,选择throws上抛。

public class exceptionTest04 {
    public static void main(String[] args) throws Exception {
        try {
           //创建输入流
           FileInputStream fis= new FileInputStream("F:\\java\\课堂笔记\\day01-课程随笔.txt");
           //读文件
           // fis.read();
           //System.out.println("以上出现异常,这里不法执行!");

            //进行数学运算
            System.out.println(100/0);//这个异常是运行时异常,编写程序时可以处理,也可以不处理

        }catch (FileNotFoundException | ArithmeticException e ){
            System.out.println("文件不存在?数字异常?都有可能!");
        }catch(IOException e){
            System.out.println("读文件报错!!!");
        }
        System.out.println("hello world!");
    }
}

异常对象有两个非常重要的方法:
获取异常简单的描述信息
String msg =exception.getMessage();
打印异常追踪的堆栈信息
exception.printStackTrace();
如何查看异常的追踪信息,快速调试程序
异常追踪信息,从上往下一行一行看。
但需要注意的是:SUN写的代码就不用了看了。主要的问题是出现在自己编写的代码上。
catch中写上 e.printStackTrack()

public class exceptionTest05 {
    public static void main(String[] args) {
        //这里只是new了异常对象,但是没有将异常对象抛出。JVM会认为这是一个普通的java对象。
        NullPointerException e = new NullPointerException("空指针异常");
        NullPointerException e2 = new NullPointerException();
        //获取异常简单描述信息,这个信息实际上就是构造方法上面的String参数。
        String mse = e.getMessage();
        System.out.println(mse);
        String mse2 = e2.getMessage();
        System.out.println(mse2);

        //打印异常堆栈信息
        //java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的。
        /*
        java.lang.NullPointerException: 空指针异常
	        at javase2.exception.exceptionTest05.main(exceptionTest05.java:13)
         */
        e.printStackTrace();
        System.out.println("hello world!");
    }
}

关于try…catch中的finally子句:
1、在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。

2、finally语句通常使用在哪些情况下呢?
通常在finally语句块中完成资源的释放/关闭。
因为finally中的代码比较有保障。
即使try语句块中的代码出现异常,finally中代码也会正常执行。

public class exceptionTest06 {
    public static void main(String[] args) {
        FileInputStream fis = null;//声明位置放到try外面,这样在finally中才能用
        try {
            //创建输入流对象
             fis= new FileInputStream("F:\\java\\课堂笔记\\day01-课程随笔.txt");
            //...
            String s = null;
            //这里一定会出现空指针异常
            s.toString();

            //流使用完需要关闭,因为流是占用资源的。
            //即使以上程序出现异常,流也必须要关闭
            //放在这里有可能流关不了
            //fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();//打印异常追踪的堆栈信息
        }catch (IOException e){
            e.printStackTrace();
        }catch (NullPointerException e){
            e.printStackTrace();
        }finally {
            //流的关闭放在这里比较保险
            if (fis != null){ //避免空指针异常
                try {
                    //close()方法有异常,采用捕捉的方式
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class ExceptionTest11 {
    public static void main(String[] args) {
        MyException e = new MyException("用户名不能为空!");
        //打印异常堆栈信息
        e.printStackTrace();//javase2.exception.MyException: 用户名不能为空!
                                   //at javase2.exception.ExceptionTest11.main(ExceptionTest11.java:5)
        //获取异常简单描述信息
        String s = e.getMessage();
        System.out.println(s);//用户名不能为空!
    }
}
public class exceptionTest07 {
    public static void main(String[] args) {
        /*
        try和finally,没有catch可以吗?可以
        try不能单独使用。
        try finally可以联合使用。

        以下代码的执行顺序:
            先执行try...
            再执行finally...
            最后执行 return (return语句只要执行,方法必然结束。)
         */

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

        //这里不能写语句,无法执行到,return一旦执行,直接结束。如果去了return,这句就可以执行。
        //System.out.println("hello world");
    }
}

public class exceptionTest08 {
    public static void main(String[] args) {
        try{
            System.out.println("try...");
            //退出JVM
            System.exit(0);//退出JVM之后,finally语句中的代码就不执行了
        }finally {
            System.out.println("finally...");
        }
    }
}

final finally finalize有什么区别?
final是一个关键字。表示最终的、不变的
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量能不能重新赋值
finally也是一个关键字,和try联合使用,使用在异常处理机制中。
finally语句块中的代码一定会执行的。
finalize()是Object类中的一个方法。作为方法名出现。所以finalize是标识符。
finalize()方法是JVM的GC垃圾回收器负责调用。

自定义异常在开发中的应用
java中如何自定义异常
1、编写一个类继承Exception或者RuntimeException。
2、提供两个构造方法,一个无参数的,一个带有String参数的。
栈操作中代码的改良,当栈满或者栈空时,不再只是return,而是采用异常处理机制的方法。
注意:throws 在方法声明位置上使用,表示上报异常信息给调用者。而throw 手动抛出异常
栈操作异常:自定义异常

public class MyStackOperationException extends Exception {
    public MyStackOperationException(){

    }
    public MyStackOperationException(String s){
        super(s);
    }
}

栈类的定义

/*
编写程序,使用一维数组,模拟栈数据结构
1、这个栈可以存储java中的任何引用类型的数组。
2、在栈中提供push方法模拟压栈。(栈满了要有提示信息)
3、在栈中提供pop方法模拟弹栈。(栈空了要有提示信息)
4、假设栈的默认初始化容量是5。
 */

public class MyStack {//栈类
    //提供一个数组来存储栈中的元素
    private Object[] elements;
    //栈帧,永远指向栈顶部元素
    //注意:最初的栈是空的,一个元素都没有
    //private int index = 0;//如果index采用0,表示栈帧指向了顶部元素的上方。
    //private int index = -1;//如果index采用-1,表示栈帧指向了顶部元素。
    private int index;
    public MyStack() {
        //一维数组动态初始化,默认初始化容量是10
        this.elements = new Object[5];
        this.index = -1;
    }

    /**
     * 压栈的方法
     * @param obj 被压入的元素
     */
    public void push(Object obj) throws MyStackOperationException {
        if(this.index>=this.elements.length-1){
            //改良之前
            //System.out.println("压栈失败,栈已满!");
            //return;

            //创建异常对象
            //MyStackOperationException e = new MyStackOperationException("压栈失败,栈已满!");
            //手动将异常抛出去
            //throw  e;

            //合并
            throw new MyStackOperationException("压栈失败,栈已满!");
        }
        //程序走到这里,说明栈没满
        //向栈中加1个元素,栈帧向上移动一个位置

        this.index++;
        this.elements[index]=obj;
        //elements[++index]=obj;
        //所有的System.out.println()方法执行时,如果输出引用的话,自动调用引用的toString()方法
        System.out.println("压栈"+obj +"元素成功,栈帧指向"+index);
    }

    /**
     * 弹栈的方法,从数组中往外取元素。每取出一个元素,栈帧向下移动一位。
     * @return
     */
    public void pop() throws MyStackOperationException {
        if(index < 0){
           
            throw new MyStackOperationException("弹栈失败,栈已空!");
            //System.out.println("弹栈失败,栈已空!");
        }else{
            System.out.print("弹栈"+this.elements[index] +"元素成功" );
            //栈帧向下移动一位
            index--;
            System.out.println("栈帧指向"+index);
        }
       // return ;
    }

    public Object[] getElements() {
        return elements;
    }

    public void setElements(Object[] elements) {
        this.elements = elements;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

测试

public class exceptionTest12 {
    public static void main(String[] args) {
        //创建对象
       MyStack stack = new MyStack();
        //压栈
        try {
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
        } catch (MyStackOperationException e) {
           // e.printStackTrace();
           //输出异常的简单信息
            System.out.println(e.getMessage());
        }

        //弹栈
        try {
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
        } catch (MyStackOperationException e) {
            //e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值