javaweb-异常,线程-011

异常概念&异常体系

异常多半是逻辑错误,违反基本法则,异常不是错误
错误编译都不会通过,连calss文件都没有
在这里插入图片描述

public class MyException {
    public static void main(String[] args) {
        int[] iInt={1,2,3};
       /* int len=4;
        if (len > 2) {
            throw new ArrayIndexOutOfBoundsException("数组越界");
        }*/

        /*int[] i=null;
        System.out.println((Objects.requireNonNull(i)));*/

        MyException myException = new MyException();
        int i = myException.testThrows();
        System.out.println(i);
    }
    public void testThrows0() throws Exception {
            throw  new Exception("你好啊,我错了");

    }
    public int testThrows()  {

        try {
            throw  new Exception("你好啊,我错了");
        } catch (Exception e) {
            return 1;
        }
        finally {
            return 0;
        }
    }
}

异常体系

异常的根类是 java.lang.Throwable ,其下有两个子类:
java.lang.Error 与 java.lang.Exception ,平常所说的异常指 java.lang.Exception 。

Throwable中的常用方法:
public void printStackTrace() :打印异常的详细信息。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。
位置,类型,原因
在这里插入图片描述
public String getMessage() :获取发生异常的原因。
提示给用户的时候,就提示错误原因。

public String toString() :获取异常的类型和异常描述信息(不用)。

异常分类

/*
java.lang.Throwable:类是 Java 语言中所有错误或异常的超类。
Exception:编译期异常,进行编译(写代码)java程序出现的问题
RuntimeException:运行期异常,java程序运行过程中出现的问题
异常就相当于程序得了一个小毛病(感冒,发烧),把异常处理掉,程序可以继续执行(吃点药,继续革命工作)
Error:错误
错误就相当于程序得了一个无法治愈的毛病(非典,艾滋).必须修改源代码,程序才能继续执行
*/
在这里插入图片描述

异常的产生过程解析

在这里插入图片描述
在这里插入图片描述

第二章 异常的处理

Java异常处理的五个关键字:try、catch、finally、throw、throws

throw关键字

throw关键字
作用:
    可以使用throw关键字在指定的方法中抛出指定的异常
使用格式:
    throw new xxxException("异常产生的原因");
    参数:
        int[] arr
        int index
    工作中我们首先必须对方法传递过来的参数进行合法性校验
    如果参数不合法,那么我们就必须使用抛出异常的方式,告知方法的调用者,传递的参数有问题
    注意:
        NullPointerException是一个运行期异常,我们不用处理,默认交给JVM处理
        ArrayIndexOutOfBoundsException是一个运行期异常,我们不用处理,默认交给JVM处理

Objects非空判断_requireNonNull方法

还记得一个类Objects吗,曾经提到过它由一些静态的实用方法组成,这些方法是null-save(空指针安
全的)或null-tolerant(容忍空指针的),那么在它的源码中,对对象为null的值进行了抛出异常操作。
public static T requireNonNull(T obj) :查看指定引用对象不是null。

Obects类中的静态方法
public static <T> T requireNonNull(T obj):查看指定引用对象不是null。
源码:
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

因为所有的类都继承了此类,因此所有的类也有此方法

throws关键字_异常处理的第一种方式,交给别人处理

声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
即是,我知道这可能有异常,你调用了我,你就来处理异常吧

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2{ }
 public void testThrows0() throws Exception {
            throw  new Exception("你好啊,我错了");
    }

throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗
号隔开。
可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别人处理),最终交给JVM处理–>中断处理
使用格式:在方法声明时使用
修饰符 返回值类型 方法名(参数列表) throws AAAExcepiton,BBBExcepiton…{
throw new AAAExcepiton(“产生原因”);
throw new BBBExcepiton(“产生原因”);
}
注意:
1.throws关键字必须写在方法声明处
2.throws关键字后边声明的异常必须是Exception或者是Exception的子类
3.方法内部如 果抛出了多个异常对象,那么throws后边必须也声明多个异常
如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
4.调用了一个声明抛出异常的方法,我们就必须的处理声明的异常
要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
要么try…catch自己处理异常

try_catch_异常处理的第二种方式,自己处理异常

如果异常出现的话,最终让vm处理会立刻终止程序,所以我们得处理异常:

  1. 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
  2. 在方法中使用try-catch的语句块来处理异常。
    try-catch的方式就是捕获异常。
    捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
    语法:
try{
	编写可能会出现异常的代码
	}catch(异常类型 e){
		处理异常的代码
		//记录日志/打印异常信息/继续抛出异常
}

Throwable类中3个异常处理的方法

如何获取异常信息:
Throwable类中定义了一些查看方法:
public String getMessage() :获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。
public String toString() :获取异常的类型和异常描述信息(不用)。
public void printStackTrace() :打印异常的跟踪栈信息并输出到控制台。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

finally代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行
不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
什么时候的代码必须最终执行?
当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开
的资源。
finally的语法:
try…catch…finally:自身需要处理异常,最终还得关闭资源。
注意:finally不能单独使用。
当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

异常注意事项_多异常的捕获处理

多个异常使用捕获又该如何处理呢?

  1. 多个异常分别处理。
  2. 多个异常一次捕获,多次处理。
  3. 多个异常一次捕获一次处理。
    一般我们是使用一次捕获多次处理方式,格式如下:
try{
	编写可能会出现异常的代码
}catch(异常类型A e){try中出现A类型异常,就用该catch来捕获.
	处理异常的代码
	//记录日志/打印异常信息/继续抛出异常
}catch(异常类型B e){try中出现B类型异常,就用该catch来捕获.
	处理异常的代码
	//记录日志/打印异常信息/继续抛出异常
}

注意:
这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异
常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

运行时异常被抛出可以不处理。即不捕获也不声明抛出。

如果finally有return语句,永远返回finally中的结果,避免该情况.(比如catch返回1,finally返回0,因为finally最后都会执行,返回0)

如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

public class Demo01Exception {
    public static void main(String[] args) {
        //1. 多个异常分别处理。
        /*try {
            int[] arr = {1,2,3};
            System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println(e);
        }
        try{
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
        }catch (IndexOutOfBoundsException e){
            e.printStackTrace();
        }
        System.out.println("继续执行");*/

        //2. 多个异常一次捕获,多次处理。
     /*   try {
            int[] arr = {1,2,3};
            //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println(e);
        }catch (IndexOutOfBoundsException e){
            System.out.println(e);
        }*/

        /*
            一个try多个catch注意事项:
                catch里边定义的异常变量,如果有子父类关系,那么子类的异常变量必须写在上边,否则就会报错
                ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
               为什么?
               因为异常对象可以直接赋给父类,多态。那么下面的子类不再执行,就会报错
         */
       /* try {
            int[] arr = {1,2,3};
            //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
        }catch (IndexOutOfBoundsException e){
            System.out.println(e);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println(e);
        }*/
        //3. 多个异常一次捕获一次处理。
       /* try {
            int[] arr = {1,2,3};
            //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
        }catch (Exception e){
            System.out.println(e);
        }*/

        //运行时异常被抛出可以不处理。即不捕获也不声明抛出。
        //默认给虚拟机处理,终止程序,什么时候不抛出运行时异常了,在来继续执行程序
        int[] arr = {1,2,3};
        System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
        List<Integer> list = List.of(1, 2, 3);
        System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
        System.out.println("后续代码!");
    }
}


异常注意事项_finally有return语句

如果finally有return语句,永远返回finally中的结果,避免该情况.
即值都被覆盖了

异常注意事项_子父类异常


/*
——————————————————————————————————————————————

    子父类的异常:
        - 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
        - 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
    注意:
        父类异常时什么样,子类异常就什么样

——————————————————————————————————————————————
 */
/*
* ——————————————————————————————————————————————
*就是父类不声明,子类只能捕获
* ——————————————————————————————————————————————
* */
public class Fu {
    public void show01() throws NullPointerException,ClassCastException{}
    public void show02() throws IndexOutOfBoundsException{}
    public void show03() throws IndexOutOfBoundsException{}
    public void show04() throws Exception {}
}

class Zi extends Fu{
    //子类重写父类方法时,抛出和父类相同的异常
    public void show01() throws NullPointerException,ClassCastException{}
    //子类重写父类方法时,抛出父类异常的子类
    public void show02() throws ArrayIndexOutOfBoundsException{}
    //子类重写父类方法时,不抛出异常
    public void show03() {}

    /*
        ——————————————————————————————————————————————
        父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。
        ——————————————————————————————————————————————
     */
    //public void show04() throws Exception{}
    //此时子类产生该异常,只能捕获处理,不能声明抛出
    public void show04()  {
        try {
            throw  new Exception("编译期异常");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第三章 自定义异常

自定义异常类

总有一些异常是特定场合下需求的,而没有被sun公司预定义,因此可以自定义一些异常,继承Exception对象
比如自定义一个业务逻辑异常: RegisterException。一个注册异常类。这个异常是自定义的,规定,重名的时候触发异常

/*
    自定义异常类:
        java提供的异常类,不够我们使用,需要自己定义一些异常类
    格式:
        public class XXXExcepiton extends Exception | RuntimeException{
            添加一个空参数的构造方法
            添加一个带异常信息的构造方法
        }
     注意:
        1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
        2.自定义异常类,必须的继承Exception或者RuntimeException
            继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
            继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理)
 */
class RegisterException extends /*Exception*/ RuntimeException{
    //添加一个空参数的构造方法
    public RegisterException(){
        super();
    }
    /*
        添加一个带异常信息的构造方法
        查看源码发现,所有的异常类都会有一个带异常信息的构造方法,
        方法内部会调用父类带异常信息的构造方法,
        让父类来处理这个异常信息
     */
    public RegisterException(String message){
        super(message);
    }
}

自定义异常类的练习

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

        List<String> sName = List.of("小明", "大小姐", "高渐离");
        MyMain myMain = new MyMain();
        while (true) {
            System.out.println("请输入注册姓名:");
            Scanner scanner = new Scanner(System.in);
            String newName = scanner.next();
            try {
                myMain.register(sName,newName);
            } catch (RegisterEx registerEx) {
                registerEx.printStackTrace();
            }
        }
    }

    public void register(List<String> list, String name) throws RegisterEx {
        if (list.contains(name)) {
            throw new RegisterEx("名字已经被注册,请重新填写");
        } else {
            System.out.println("注册成功");
        }
    }
}

第四章 多线程

并发与并行

并发:指两个或多个事件在同一个时间段内发生。
并行:指两个或多个事件在同一时刻发生(同时发生)。

进程概念

进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多
个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创
建、运行到消亡的过程。
线程:线程是进程中的一个功能执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程
中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

线程概念

线程调度:
分时调度
所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度
优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为
抢占式调度。
设置线程的优先级

抢占式调度详解
CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而
言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是
在同一时刻运行。 其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的
使用率更高。

主线程

在这里插入图片描述

创建多线程程序的第一种方式_创建Thread类的子类

Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。

实现步骤:
    1.创建一个Thread类的子类
    2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
    3.创建Thread类的子类对象
    4.调用Thread类中的方法start方法,开启新的线程,执行run方法
         void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
         结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其 run 方法)。
         多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
java程序属于抢占式调度,那个线程的优先级高,那个线程优先执行;同一个优先级,随机选择一个执行
如下:分别打印一个次级线程和一个主线程,交错执行
public class MyMain {
    public static void main(String[] args) {
        MyThread myThread = new MyThread("打印数字");
        myThread.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main"+i);
        }
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值