zoukankan      html  css  js  c++  java
  • JavaSE学习笔记

    • 程序在执行的过程中出现非正常的情况,最终导致 JVM 非正常停止。异常在 Java 中以类的形式存在,每一个异常类都可以创建对象,在产生异常的时候就是创建了一个异常类的对象,然后将异常对象抛出。
    public class Main {
        public static void main(String[] args) {
            NullPointerException exception = new NullPointerException("空指针异常");
            System.out.println(exception);//java.lang.NullPointerException: 空指针异常
        }
    }
    

    异常继承结构图

    在这里插入图片描述
    编译时异常和运行时异常都发生在运行阶段

    异常的分类

    • 大类参考上面异常继承结构图

    RuntimeException

    • 错误的强制类型转换
    • 空指针异常
    • 数组越界异常
    • 这种异常是可以通过程序检查来避免的

    • 除了 RuntimeException,其余的所有异常都是检查型异常,在编译时期就要对这种异常进行处理,否则编译器就会报错。对这种异常处理有两种方式,一种是使用 throws 异常将异常抛出,抛给调用者,然后调用者也可以选择抛出或者直接处理这个异常,这种方式如果在某一个地方发生了异常,那么程序将终止,不会在继续向下执行。另外一种方式就是使用 try...catch...finally 来处理这个异常,finally 关闭资源以后,程序可以继续向下执行。
    • 在异常发生的时候,如果一直上抛给调用者,那么最终给抛给 main 方法,main 方法继续上抛异常的话,那么这个异常就会抛给 JVM,然后 JVM 就会终止程序的运行。
    • 异常机制可以提高程序的健壮性

    编译时异常

    public class Main {
        public static void main(String[] args) throws ParseException {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            //date = sdf.parse("2020-1-1 00:00:00");//Wed Jan 01 00:00:00 CST 2020
            date = sdf.parse("2020-1-1");//java.text.ParseException: Unparseable date: "2020-1-1"
            //这里格式不对,所以程序中断抛出异常,程序不再往下进行
            //如果不想让程序中断,那么就可以对这个异常进行捕获处
            System.out.println(date);
        }
    }
    
    //捕获异常
    public class Main {
        public static void main(String[] args) {
            Date date = new Date();
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                date = sdf.parse("2020-1-1");//java.text.ParseException: Unparseable date: "2020-1-1"
            } catch (ParseException e) {
                e.printStackTrace();//java.text.ParseException: Unparseable date: "2020-1-1"
            }
            //这里对异常进行了捕获,所以程序在发生异常的时候并没有中断程序
            System.out.println(date);//Fri Jul 31 15:28:21 CST 2020
        }
    }
    

    运行时异常

    public class Main {
        public static void main(String[] args) {
            String str = "abc";
            System.out.println(str.charAt(3));
            //StringIndexOutOfBoundsException: String index out of range: 3
            //运行时异常要进行捕获处理
            System.out.println(str);
        }
    }
    
    //捕获异常
    public class Main {
        public static void main(String[] args) {
            try {
                System.out.println(3 / 0);
            } catch (Exception e) {
                //java.lang.ArithmeticException: / by zero
                //e.printStackTrace();
                System.out.println(e.getMessage());/// by zero
            }
            System.out.println(3);
        }
    }
    

    异常的产生

    public class Main {
        public static void main(String[] args) throws ParseException {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            //date = sdf.parse("2020-1-1 00:00:00");//Wed Jan 01 00:00:00 CST 2020
            date = sdf.parse("2020-1-1");//java.text.ParseException: Unparseable date: "2020-1-1"
            //这里格式不对,所以程序中断抛出异常,程序不再往下进行
            //如果不想让程序中断,那么就可以对这个异常进行捕获处
            System.out.println(date);
        }
    }
    
    //parse源码
    public Date parse(String source) throws ParseException {
        ParsePosition pos = new ParsePosition(0);
        Date result = parse(source, pos);
        if (pos.index == 0)
            throw new ParseException("Unparseable date: "" + source + """ ,
               pos.errorIndex);
        return result;
    }
    
    • 通过上面的源码我们可以看出,如果日期的格式不正确那么 JVM 就会检测出来这个异常,此时 JVM 会创建一个异常类对象,这个异常类对象包含了异常产生的原因,位置和内容,使用 throw 手动抛出异常,然后使用红色的字体打印在控制台,然后 JVM 终止当前的程序。

    手动抛出异常

    public class Main {
        public static void main(String[] args) throws ParseException {
            //Exception in thread "main" java.lang.RuntimeException: 除数不能为 0
            //System.out.println(div(1, 0)); //程序中断,往下执行
            try {
                System.out.println(div(1, 0));
            } catch (Exception e) {
                System.out.println(e.getMessage());//除数不能为 0
            }
            System.out.println(div(1, 1));//1
        }
        public static int div(int a, int b) {
            if(b == 0) throw new RuntimeException("除数不能为 0");
            return a / b;
        }
    }
    

    自定义异常类

    public class NullPointerException extends RuntimeException {
        private static final long serialVersionUID = 5162710183389028792L;
    
        /**
         * Constructs a {@code NullPointerException} with no detail message.
         */
        public NullPointerException() {
            super();
        }
    
        /**
         * Constructs a {@code NullPointerException} with the specified
         * detail message.
         *
         * @param   s   the detail message.
         */
        public NullPointerException(String s) {
            super(s);
        }
    }
    
    • Java 中提供的异常类不能够处理所有的异常,通过查看源码,我们可以发现所有的异常类中都有两个方法,这个一无参构造方法,一个是有参构造方法。自定义异常类必须继承 (Exception) 或者 (RuntimeException),如果是发生概率小的异常可以继承 (RuntimeException),表示运行时异常;否则继承 (Exception),编译时异常,在编译阶段就要对异常进行处理。
    public class MyException extends Exception {
        public MyException() {
        }
    
        public MyException(String message) {
            super(message);
        }
    }
    
    public class Main {
        public static void main(String[] args) throws MyException {
            try {
                System.out.println(div(1, 0));
            } catch (Exception e) {
                System.out.println(e.getMessage());//除数不能为 0
            }
            System.out.println(div(1, 0));//自己不处理,抛给虚拟机
            //Exception in thread "main" cn.edu.zut.MyException: 除数不能为 0
        }
    
        public static int div(int a, int b) throws MyException {
            //自定义的异常在使用的时候是要抛给调用者去处理的
            //所以这里不进行处理
            //MyException exception = new MyException("除数不能为 0");
            //if(b == 0) exception;
            if(b == 0) throw new MyException("除数不能为 0");
            return a / b;
        }
    }
    

    在继承机制中,子类的方法抛出的异常不能比父类方法抛出的异常还要多

    final finally finalize

    • final:关键字,最终的,不变的
    • finally:关键字,在异常机制中,必然会执行,在发生异常的时候程序会终止,那么如果使用流的时候可能会打开一些资源,那么这些资源将不会被处理,如果使用 finally,不管程序是否发生异常,程序都会进入 finally 执行程序,此时在 finally 中就可以关闭一些资源,避免空间的浪费。(如果在进入 finally 程序代码块之前退出了 JVM 虚拟机,那么 finally 中的代码将不再执行。)
    • finalize:Object 类中的一个方法,GC 负责调用这个方法进行垃圾回收。
    public class Main {
        public static void main(String[] args) {
            System.out.println(print());//100
        }
        public static int print() {
            int x = 100;
            try {
                return x;
            } finally {
                x ++;
            }
        }
    }
    
    • 我们知道 finally 中的程序一定会被执行,但是 Java 中又规定 Java 方法体中的代码必须自上而下的执行,return 一旦执行,整个方法必须结束。在 IDEA 中我们可以直接查看 .class 文件,然后查看其执行过程。
    public class Main {
        public Main() {
        }
    
        public static void main(String[] args) {
            System.out.println(print());
        }
    
        public static int print() {
            byte x = 100;
    
            byte var1;
            try {
                var1 = x;
            } finally {
                int var5 = x + 1;
            }
    
            return var1;
        }
    }
    
    
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/zut-syp/p/13570744.html
Copyright © 2011-2022 走看看