异常Exception

异常Exception,第1张

 java中所有错误的超类为:Throwable。有两个子类:Error和Exception

Error的子类描述的都是系统错误,比如虚拟机内存溢出

Exception的子类描述的都是程序错误,比如空指针,下标越界

异常处理机制中的try-catch

语法

try{
    可能出现异常的代码段
}catch(XXXException e){
    try语句块中出现XXXException后的处理代码
}

try语句不能单独写,后面必须跟catch或finally

try语句中出错代码以下的内容不会被执行

public class TryCatchDemo {
    public static void main(String[] args) {
        System.out.println("程序开始了...");
        try {
            String str = "abc";
            System.out.println(str.length());

            System.out.println(str.charAt(0));

            System.out.println(Integer.parseInt(str));

            System.out.println("!!!!!!");
        }catch (NullPointerException | StringIndexOutOfBoundsException e) {
            System.out.println("出现了空指针或字符串下标越界异常!");
        }catch (Exception e) {
            System.out.println("反正就是出个错!");
        }
        System.out.println("程序结束了...");
    }
}

输出结果为

 “!!!!!!”没有输出

可以用多个catch,且catch可以用“|”来合并

fianlly

finally块是异常处理机制的最后一块,它可以直接跟在try语句块之后或者最后一个catch块之后

只要程序执行到try语句块,无论try中代码是否出现异常,最终fianlly都必定执行,通常我们会将释放资源这类 *** 作放到finally中确保执行

public class FinallyDemo {
    public static void main(String[] args) {
        System.out.println("程序开始了");
        try{
//            String str = null;
            String str = "abc";
            System.out.println(str.length());
            return;
        }catch(Exception e){
            System.out.println("出现了错误");
        }finally{
            System.out.println("finally中的代码执行了!");
        }
        System.out.println("程序结束了");
    }
}
throw

throw关键字可以主动对外抛出一个异常实例,通常下列两种情况需要:

  1. 当前代码片段出现了异常,但是该异常不应当在当前代码片段执行,所以对外抛出
  2. 当前程序出现了满足语法,但是不满足业务场景时,也可以当做异常抛出。例如:输入用户年龄为10000岁,这不符合正常现象,所以将这当做与异常抛出
    public class Person {
        private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) throws Exception {
            if(age<0||age>100){
    //            throw new RuntimeException("年龄超过了范围!");
                /*
                    当我们使用throw主动抛出一个异常时,就必须在方法上使用throws声明该异常的抛出通知调用者
                    处理该异常。RuntimeException是一个例外。
                 */
                throw new Exception("年龄超过了范围!");
            }
            this.age = age;
        }
    }
    public class ThrowDemo {
        public static void main(String[] args) {
            Person p = new Person();
            try {
                /*
                    当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理该异常
                    处理方式有两种可选:
                    1:可使用try-catch捕获该异常(当前代码的演示)
                    2:可以在当前方法上继续使用throws声明将异常抛出
                    实际情况应当结合实际的业务场景分析决定。
                 */
                p.setAge(10000);//满足语法不满足业务
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("我今年:"+p.getAge()+"岁");
        }
    }
    throws

子类在重写超类中含有throws声明异常抛出的方法时对throws的重写规则

public class ThrowsDemo {
    public void dosome()throws IOException, AWTException {}
}

class SubClass extends ThrowsDemo{
//    public void dosome()throws IOException, AWTException {}

    //允许子类方法不再抛出任何异常
//    public void dosome(){}

    //允许子类方法抛出部分异常
//    public void dosome()throws IOException{}

    //允许子类方法抛出超类方法声明异常的子类型异常
//    public void dosome()throws FileNotFoundException {}

    //不允许子类抛出额外异常(超类方法上没有的且没有继承关系的异常)
//    public void dosome()throws SQLException {}

    //不允许子类抛出比超类方法声明的异常还大的异常
//    public void dosome()throws Exception {}

}

 即子类重写超类中含有throws声明异常抛出的方法时,子类可以不抛出异常,也可以抛出(父类所抛出异常)的子类或者本身,不能抛出(父类抛出异常)的父类或者与(父类抛出异常)不相关的异常。

要注意的是:非检查异常RuntimeException异常可以在子类抛出,RuntimeException的子类有NullPointException,IndexOutOfBounds等

try-catch改进

原本的异常处理机制在IO中的应用方式

import java.io.FileOutputStream;
import java.io.IOException;

public class FinallyDemo2 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("fos.dat");
            fos.write(1);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

JDK7之后,java推出了一个新的特性:自动关闭

语法

 try(
       定义并初始化需要在finally中调用close关闭的类实例
 ){
 
  }catch(XXXException e){
 
  }
public class AutoCloseableDemo {
    public static void main(String[] args) {
        try(
                //只有实现了AutoCloseable接口的类才可以在这里定义,并最终编译器会改为在finally中调用close()
                //编译后的代码参照FinallyDemo2的样子
                FileOutputStream fos = new FileOutputStream("fos.dat");
                //String没有实现该接口,不能在这里定义
//                String str = "abc";
        ){
            fos.write(1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

输入输出流都可以在try()中定义,并且会将它自动关闭,不用在finally人工关闭

fianlly 题目分析
public class FinallyDemo3 {
    public static void main(String[] args) {
        System.out.println(
                test("0")+","+test(null)+","+test("")
        );
    }
    public static int test(String str){
        try{
            return str.charAt(0) - '0';
        }catch(NullPointerException e){
            return 1;
        }catch(Exception e){
            return 2;
        }finally {
            return 3;
        }
    }
}

结果为3,3,3

分析:

在调用test("0")时,系统会先设一个return有关的值,即因为test的返回值为int,所以设一个int型的变量a,用于存储test的返回值。所以,调用test("0")时,先进行try语句块,得到值为0,就将0赋给变量a,由于一旦执行了try语句块,就必须执行finally语句块,所以,就将3的值赋给a,所以返回值为3,后面两个同理。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/872061.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存