【Java】异常Exception & 线程 - 练习题

本文深入探讨Java异常处理机制,包括异常体系、throw与throws区别、异常处理方式及常见异常解析。同时,讲解并行、并发概念,进程与线程的关系,并提供多线程编程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常


1、异常系列的超父类:java.lang.Throwable

(1)只有它或它子类的对象,才能被JVM或throw语句“抛”出

(2)也只有它或它子类的对象,才能被catch“捕获”

2、Throwable分为两大派别

(1)Error:严重的错误,需要停下来重新设计、升级解决这个问题

(2)Exception: 一般的异常,可以通过判断、检验进行避免,或者使用try…catch进行处理

3、Exception又分为两大类

(1)运行时异常:

​ 它是RuntimeException或它子类的对象。

​ 这种类型的异常,编译器不会提醒你,要进行throws或try…catch进行处理,但是运行时可能导致崩溃。

(2)编译时异常:

​ 异常除了运行时异常以外的都是编译时异常。

​ 这种类型的异常,编译器是强制要求你,throws或try…catch进行处理,否则编译不通过。

4、列出常见的异常类型

(1)运行时异常

RuntimeException、NullPointerException(空指针异常),ClassCastException(类型转换异常),ArithmeticException(算术异常),NubmerFormatException(数字格式化异常),IndexOutOfBoundsException(下标越界异常)(ArrayIndexOutOfBoundsException(数组下标越界异常)、StringIndexOutOfBoundsException(字符串下标越界异常))、InputMisMatchException(输入类型不匹配异常)。。。。

(2)编译时异常

FileNotFoundException(文件找不到异常)、IOException(输入输出异常)、SQLException(数据库sql语句执行异常)。。。

练习一:异常的体系

问题:

  1. 请描述异常的继承体系

  2. 请描述你对错误(Error)的理解

  3. 请描述你对异常(Expection的理解)

  4. 请描述你对运行时异常(RuntimeException)的理解

答:

  1. 异常继承体系为:异常的根类是 java.lang.Throwable,其下有两个子类:
    java.lang.Error 与 java.util.Exception 。而Exception又分为编译时期异常:checked异常,与运行时期异常:runtime异常。

  2. Error:表示不可修复的恶性的错误,只能通过修改代码规避错误的产生,通常是系统级别的,所以很严重。

    Error 很严重

  3. Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且应该通过代码的方式纠正,使程序继续运行,是必须要处理的。

  4. 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。

练习二:throw与throws的区别

问题:

  1. 请描述throw的使用位置,作用是什么?

  2. 请描述throws的使用位置,作用是什么?

答:

  1. throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行。

  2. throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处。

练习三:异常的处理方式

问题:

  1. 异常处理方式有几种,分别是什么?

  2. 详细阐述每种方式对异常是如何处理的

答:

  1. 异常的处理方式有两种,分别是使用throws和try…catch…finally

  2. throws用在方法的声明上后接异常类名,是把异常抛给调用者进行处理

  3. try…catch…finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行

a) try代码块中是可能出现异常的代码

b) catch代码块,是遇到异常,对异常进行处理的代码

c) finally代码块是无论是否发生异常,都必须执行的代码,用于释放资源.

练习四:常见异常,及产生原因

问题:请列举常见异常,并说明产生原因。

答:

NullPointerException:指针异常。

​ 当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度等等。

ArrayIndexOutOfBoundsException:数组索引越界异常。

当对数组的索引值为负数或大于等于数组大小时抛出此异常。

ArithmeticException:算术运算异常。

​ 程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了。

NumberFormatException:数字格式异常。

​ 当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。

练习五:看代码,分析结果

问题:根据给出的相应代码,分析可能产生的结果

1.举例

public class Test1 {
    public static void main(String[] args) {
        String str = null;
        System.out.println(str.length());//Exception in thread "main" java.lang.NullPointerException
    }
}

答:变量str的值为null,调用方法时,报空指针异常NullPointerException

变量str的值为null,调用字符串对象length()方法时,报空指针异常NullPointerException

2.举例:

public class Test2 {
    public static void main(String[] args) {
        int arr[] = {1, 2};
        System.out.println(arr[2]);
    }
}

答:索引值2大于等于数组arr的长度时,报数组索引越界异常ArrayIndexOutOfBoundsException

3.举例:

public class Test3 {
    public static void main(String[] args) {
        System.out.println(1/0);//Exception in thread "main" java.lang.ArithmeticException: / by zero
    }
}

答:整数0做了分母,报算术运算异常ArithmeticException:/by zero

4.举例:

public class Test4 {
    public static void main(String[] args) {
        System.out.println(Integer.parseInt("java"));
        //Exception in thread "main" java.lang.NumberFormatException: For input string: "java"
        //	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        //	at java.lang.Integer.parseInt(Integer.java:580)
        //	at java.lang.Integer.parseInt(Integer.java:615)
        //	at cn.liuawen.exception.Test4.main(Test4.java:11)
    }
}

答:把字符串“java”转换为Integer类型时,当然会报数字格式化异常啦NumberFormatException

5.举例:

public class Test5 {
    public static void main(String[] args) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
        try {
            Date date = format.parse("2020-05-29");
            System.out.println("程序正常");
            System.out.println(date);
            //Wed Jan 29 00:05:00 CST 2020
        } catch (ParseException e) {
            System.out.println("程序异常");
        }
        //程序正常
    }
}

答:
打印结果“程序正常”.try代码块中并没有产生异常,catch代码块中的代码不会执行。date为Wed Jan 29 00:05:00 CST 2020。

练习六:并行、并发概念

问题:请简单描述什么是并行,什么是并发?

答:

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

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

通俗易懂版:

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不 支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。

所以它们最关键的点就是:是否是『同时』。

并发(Concurrency)是同时处理很多事情(dealing with lots of things at once),并行(Parallelism)是同时执行很多事情(doing lots of things at once);并行是并发的子集。

并发 同一时间段内发生

并行 同时发生

练习七:进程概念、线程概念、线程与进程联系

问题:请描述什么是进程,什么是线程,进程与线程之间的关系,并举例说明。

答:

进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

一个程序运行后至少有一个进程,一个进程中可以包含多个线程,但一个进程中至少包含一个线程。比如使用迅雷软件下载网络文件时,同时下载多个文件,就使用到了多线程下载。

练习八:自定义异常类

问题:

请使用代码实现

每一个学生(Student)都有学号,姓名和分数,分数永远不能为负数

如果老师给学生赋值一个负数,抛出一个自定异常

NoScoreException

/*
 1.定义异常类NoScoreException,继承RuntimeException
a)提供空参和有参构造方法
 */
public class NoScoreException extends RuntimeException {
    //  空参构造
    public NoScoreException() {
        super();
    }

    // 有参构造
    public NoScoreException(String message) {
        super(message);
    }
}


/*
  2.定义学生类(Student)
 a)属性:name,score
 b)提供空参构造
 c)提供有参构造;
  i.使用setXxx方法给名称和score赋值
 d)提供setter和getter方法
  i.在setScore(int score)方法中
   1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
   2.然后在给成员score赋值.
 */
public class Student {
    private String name;
    private int score;

    // 空参构造
    public Student() {
        super();
    }

    // c)提供有参构造;
// i.使用setXxx方法给名称和score赋值
    public Student(String name, int score) {
        setName(name);
        setScore(score);
    }
// d)提供setter和getter方法

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    // i.在setScore(int score)方法中
    public void setScore(int score) {
// 1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
        if (score < 0) {
            throw new NoScoreException(":分数不能为负数:" + score);
        }
// 2.然后在给成员score赋值.
        this.score = score;
    }
}
/*
3.定义测试类TestStudent
 a)提供main方法,在main方法中
  i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
  ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码
  iii.使用空参构造创建Student对象
  iv.调用setScore(int score)方法,传入一个正数,运行程序
  v.调用setScore(int score)方法,传入一个负数,运行程序
 */

public class TestStudent {
    public static void main(String[] args) {
//  i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
//  Student s = new Student("xxx", -10);
//  ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码

//  iii.使用空参构造创建Student对象
        Student s = new Student();
//  iv.调用setScore(int score)方法,传入一个正数,运行程序
        s.setScore(100);
//  v.调用setScore(int score)方法,传入一个负数,运行程序
        s.setScore(-5);//Exception in thread "main" cn.liuawen.exception.NoScoreException: :分数不能为负数:-5
    }
}

练习九:多线程

问题:

创建多线程对象,开启多线程。在子线程中输出1-100之间的偶数,主线程输出1-100之间的奇数。

答:

自定义线程类

public class MyThread extends Thread {

    /**
     * 重写run方法,完成该线程执行的逻辑
     */
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println("子线程打印输出偶数:" + i);
            }
        }
    }
}

测试类

public class TestThread {
    public static void main(String[] args) {
//创建自定义线程对象
        MyThread mt = new MyThread();
//开启线程
        mt.start();
//在主方法中执行for循环
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 1) {
                System.out.println("主线程打印输出奇数:" + i);
            }
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值