Java:异常详解、线程

版权声明:版权归 你的pizza到了 所有,未经允许不可转载 https://blog.csdn.net/qq_38353993/article/details/82593060

1、异常-概念及作用

1)、异常:程序运行时JVM遇到无法处理的数据或表达式

2)、JVM遇到这种异常,通常会在控制台打印异常信息,然后结束掉程序,不进行下面的程序

3)、“异常处理”就是允许程序遇到这段异常时,可跳过这段代码,继而进行下面的代码

需要在编写代码前,就预知会产生这样的异常,从而做出预先的处理

2、异常-异常产生的过程解析

1)、JVN执行到有异常的代码;

2)、JVM要识别到这样的异常;

3)、JVM到类库中找到描述这个异常的”异常类”,并创建对象;

4)、判断代码中是否希望捕获这种异常

–是:执行捕获异常的代码

–否:控制台打印异常信息,结束程序(不希望这样)

3、异常-Java异常体系结构及分类

Throwable(异常的顶层父类):

1)、Error:无法处理,不希望程序捕获

2)、Exception:可以处理,希望程序捕获的异常

RuntimeException(运行时异常):Java不要求强制捕获这种异常,可以通过判断进行避免

除RuntimeException外的其他异常(编译器异常):Java要求必须强制捕获并处理,否则无法编译通过,这种异常无法通过判断进行避免

4、异常处理-基本方式try…catch语句及执行流程

语法:

try{
    //可能出现异常的代码,出现异常时,后面代码不会再继续执行,转而执行catch中的代码
}catch(异常类名 变量名){
    //如果try中出现了异常类名的异常,这里会进行捕获
    //出现异常后的处理代码
}

代码:

public static void main(String[] args) {
    updateStudent();
}
public static void updateStudent(){
    Scanner sc = new Scanner(System.in);
    while(true) {
        System.out.println("请输入学号:");
        try {
            int stuNo = sc.nextInt();
            System.out.println("你输入的学号是:" + stuNo);
            break;//正常情况,结束循环
        } catch (InputMismatchException e) {
            System.out.println("你的输入有误!");
            sc = new Scanner(System.in);
        }
    }
    System.out.println("后续代码....");
}

执行流程图:

这里写图片描述

5、异常处理-常见的几种异常

1)、空指针异常:NullPointerException运行时异常

String s = null;
System.out.println(s.length());//编译通过,运行时抛出NullPointerException

要做非空判断,在开发时,要在方法返回时做非空判断(代码会更加健壮)

2)、数组下标越界异常:ArrayIndexOutOfBoundsException:运行时异常

int[] arr = {1,2,3};
System.out.println(arr[3]);//产生异常,没有3这个索引

3)、数字转换异常:NumberFormatException:运行时异常

String str = 12a;
int a = Integer.parseInt(str);//产生异常

4)、算术运算异常:ArithmeticException运行时异常

int a = 9;
int b = 0;
c = a/b;//产生异常

5)、转换异常:ParseException编译期异常,必须捕获,否则编译会异常

String str = "2018-08-08";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try{
    Date date = sdf.parse(str);
}catch(ParseException e){//必须对异常进行捕获
    .....
}

6、异常处理-try..catch…catch语句及执行流程

老中医Exception必须放在其他具体异常后面

执行流程图:

这里写图片描述

7、异常处理-声明抛出异常throws

public static void main(String[] args)  {
    int[] arr = {432, 432, 43, 253};
    try {
        System.out.println("总和:" + sum(arr));
    } catch (NullPointerException e) {
        System.out.println("调用方法,接收到一个异常....");
    }
    System.out.println(sum(null));
}

public static int sum(int[] arr) throws NullPointerException,
ArrayIndexOutOfBoundsException,ArithmeticException {//抛出异常在方法调用处就要用try...catch进行捕获
    int sum = 0;
    for (int n : arr) {
        sum += n;
    }
    return sum;
}

注意:如果throws后面的是“编译期异常”,调用的代码必须要使用try…catch…或者继续抛出,否则编译错误。如果throws后面的是“运行时异常”,调用处可以不处理,编译可以通过,但不建议。

8、异常的处理-抛出异常对象throw

public static void main(String[] args)  {
    int[] arr = {432, 432, 43, 253};
    try {
        System.out.println("总和:" + sum(null));
    } catch (NullPointerException e) {
        System.out.println("调用方法,接收到一个异常....");
        System.out.println("异常信息:" + e.getMessage());
    }
}

public static int sum(int[] arr)  {
    int sum = 0;
    if (arr == null) {
        throw new NullPointerException("哥们,你给我传了一个空指针,你太坏了....");
    }

    for (int n : arr) {
        sum += n;
    }
    return sum;
}

注意:如果throw抛出的是一个“运行时异常”,调用处可以不处理,但是不建议;如果throw抛出了一个“编译期异常”,方法声明处必须显示的使用throws声明此异常,调用处也必须处理,否则编译错误;

9、throws和throw的差别

throws:表示“声明”此方法可能会产生某种异常,如果产生,请JVM将此异常对象抛给调用者。如果没有产生异常,则正常执行完毕。

public static void sum() throws NullPointerException{
    ...
}

throw:表示立即“抛出一个异常对象”

public static void sum(){
    if(...){
    throw new NullPointerException("...");
    }
}

方法throw异常对象,就是为了程序在执行流程中,调用方法时产生异常后chatch异常,进而进行捕获到异常后的处理代码(简单的说就是告诉执行流程,这个方法异常了,你处理下 ps:这个异常是可以自定义发生什么才抛出什么异常)

10、异常的处理-Objects类的非空判断

class Student{
        private String name;//要求姓名不能为:null
        ....
        public Student(String name){
            /*
            if(name == null){
                throw new NullPointerException("...");
            }
            if(...){
            }*/

            this.name = Objects.requireNonNull(name);//省去一个非空判断
        }
    }
main(){
    Student stu = new Student("张三");
    Student stu2 = new Student(null);
}

11、异常的处理-try…catch…finally语句

在try…catch中先执行finally再进行return

public static void main(String[] args) {
    String s = show();
    System.out.println("返回值:" + s);
}
public static String show(){
    try {
        System.out.println("1.打开文件");
        System.out.println("2.读取文件--出异常" + (10 / 0));
        return "呵呵呵";
    } catch (Exception e) {

        System.out.println("异常了....");
        return null;
    }finally {//无论是否有异常,永远在return前执行
        System.out.println("3.关闭文件");
    }
}

12、自定义异常-概述

当类库中没有我们需要的异常类时,可以自定义一个异常类:

class Student{
    private int age;
    public void setAge(int age){
    //假如我们要求年龄必须在15到50之间
    if(age < 15 || age > 50){
        throw new 自定义异常();
    }
    this.age = age;
    }
}

13、自定义练习:

自定义异常类:继承Exception或者其子类(RuntimeException或非RuntimeException(建议使用,强制对异常进行抛出))

添加一个String参数的构造方法,用于设置“异常信息”

异常类:

public class AgeException extends Exception{
    public AgeException(String msg) {
        super(msg);//调用父类的构造方法
    }
}

使用异常类对对象类内容加以限制

public class Student {
    private int age;
    public void setAge(int age) throws AgeException {
        if (age < 15 || age > 50) {
            throw new AgeException("年龄错误,必须在15到50岁之间!");
        }
        this.age = age;
    }
}

测试类:

public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        try {
            stu.setAge(100);
        } catch (AgeException e) {//捕获异常执行下面的代码
            System.out.println("异常信息:" + e.getMessage());
        }
    }
}

13、多线程-进程与线程

1)、进程:操作系统的概念,一个独立运行的程序,就是一个进程;

2)、线程:线程是由进程创建的,一个进程可以创建任意多的线程,每个线程都包含一些代码,线程中的代码会同主线程或其他线程同时运行;

3)、多进程:某个时间段内,同时运行多个程序;

4)、多线程:一个程序可以同时启动多个线程,也就是多段代码可以同时运行,提高程序的运行效率

单线程:只能做一件事

需要程序能够同时做多件事,就要制作多线程程序

14、多线程-并发与并行

1)、并行:多个线程同时开始运行;

2)、并发:多个线程同时访问同一个资源(CPU)。

15、多线程-创建线程类-继承Thread及匿名对象的方式

1)、制作多线程程序,在设计阶段就要确定(那些代码需要独立的运行起来,从而制作线程类)

2)、创建多线程步骤:

–定义线程类,继承Thread

–重写run()方法

–启动线程

创建一个线程对象;

调用对象的start()方法启动线程;

线程类:

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("从网络接收外部数据....");

        }
    }
}

在测试类中启动线程:

public static void main(String[] args) {
    //先启动线程
    MyThread t = new MyThread();
    t.start();//启动线程后,主方法继续向下运行

    for (int i = 0; i < 1000; i++) {
        System.out.println("从控制台接收数据.....");
    }
}

16、多线程-创建线程类-关于线程的几个说明

1)、匿名内部类实现线程:

new Thread(){
    public void run(){
        for (int i = 0; i < 1000; i++) {
            System.out.println("从控制台接收数据.....");
        }
    }
}.start();

2)、重写的是run()方法,但是在启动线程时是使用start()方法

3)、对于一个线程对象,只能调用一次start()方法,不能多次调用(编译时能通过,但是运行时会报错)

复习

  • [ ] 能够辨别程序中异常和错误的区别

    Error错误:例如:内存溢出,异常中不进行捕获的重大错误

    Exception异常:我们希望程序进行捕获处理的,进而使程序可以继续进行下去

  • [ ] 说出异常的分类

    运行时异常(RuntimeException):程序可以不进行处理

    非运行时异常:程序必须进行捕获处理的异常,处理之后程序菜能运行下去

  • [ ] 说出虚拟机处理异常的方式

    执行带存在异常的代码

    JVM识别异常

    JVM在类库中寻找对应异常类,创建对象

    判断代码是否catch这个异常:

    catch到了:执行catch中的代码;

    没有cahtch到:在控制台打印异常信息,结束程序

  • [ ] 列举出常见的三个运行期异常

    空指针异常NullPointerException

    数组下边越界异常ArrayIndexOutOfboundsException

    运算异常ArithmeticException

  • [ ] 能够使用try…catch关键字处理异常

    try{
      //会出现异常的代码
    }catch(异常类名 变量名){
      //捕获异常后的处理代码
    }
  • [ ] 能够使用throws关键字处理异常

    public static void show() throws Exception{}
  • [ ] 能够自定义异常类

    public calss myException extends Exception{
      public myException(String str){
          super(str)
      }
    }
  • [ ] 能够处理自定义异常类

    class Person{
      int a = 0;
      public void addA(int a){
          Scanner scanner = new Scanner(System.in);
          a = scanner.nextInt();
          if(a == 0){
              threw new myException("a不能为零")
          } 
      }
    }

    测试:

    Person people = new Person();
    try{
      people.addA(0)
    }catch(myException e){
      System.out.println(e.getMessage());
    }
    
  • [ ] 说出进程的概念

    操作系统中运行的一个程序

  • [ ] 说出线程的概念

    一个进程可以由多个线程组成

  • [ ] 能够理解并发与并行的区别

    1).什么是并行:多个线程同时开始运行;

    2).什么是并发:多个线程同时访问同一资源(CPU)。

  • [ ] 能够开启新线程

    创建线程类

    class MyThread extends Thread{
      public void run(){
          //线程开始时要做的事儿
      }
    }

测试类中启动线程:

MyThread m = new MyThread();
m.start();

猜你喜欢

转载自blog.csdn.net/qq_38353993/article/details/82593060