JavaSE-09笔记【异常(+2024新)】

文章目录

  • 1. 异常概述
  • 2.异常继承结构
    • 2.1 编译时异常和运行时异常区别
    • 2.2 如何让异常发生(throw关键字)
  • 3.自定义异常
  • 4.异常的处理
    • 4.1 第一种处理方式:声明异常 (throws关键字)
    • 4.2 第二种处理方式:捕捉异常 (try...catch...关键字)
      • 4.2.1 catch可以写多个,并且遵循自上而下,从小到大(其可以看作是分支,最多只有一个catch会被执行)
      • 4.2.2 Java7新特性:catch后面小括号中可以编写多个异常,使用运算符“|”隔开。
  • 5.异常的使用
  • 6.异常的常用方法
  • 7.finally语句块
    • 7.1 finally的初步使用
    • 7.2 final、finally、finalize分别是什么?
    • 7.3 finally相关面试题
  • 8.方法覆盖与异常

1. 异常概述

  1. 什么是异常?有什么用?
  • Java中的异常是指程序运行时出现了错误或异常情况,导致程序无法继续正常执行的现象。例如,数组下标越界、空指针异常、类型转换异常等都属于异常情况。
  • Java提供了异常处理机制,即在程序中对可能出现的异常情况进行捕捉和处理。异常机制可以帮助程序员更好地管理程序的错误和异常情况,避免程序崩溃或出现不可预测的行为。
  • 没有异常机制的话,程序中就可能会出现一些难以调试和预测的异常行为,可能导致程序崩溃,甚至可能造成数据损失或损害用户利益。因此,异常机制是一项非常重要的功能,是编写可靠程序的基础。
  1. 异常在Java中以类和对象的形式存在。
  • 现实生活中也有异常,比如地震,火灾就是异常。也可以提取出类和对象,例如:
    ①地震是类:512大地震、唐山大地震就是对象。
    ②空指针异常是类:发生在第52行的空指针异常、发生在第100行的空指针异常就是对象。也就是说:在第52行和第100行发生空指针异常的时候,底层一定分别new了一个NullPointerException对象。

一个示例:

package exceptiontest;

public class ExceptionTest01 {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
//        int c = a / b; //运行后抛出异常:Exception in thread "main" java.lang.ArithmeticException: / by zero
//                       //at exceptiontest.ExceptionTest01.main(ExceptionTest01.java:7)
//                       //抛出这个异常的时候底层是new了一个ArithmeticException对象
//        System.out.println(a + "/" + b + " = "+ c);

        String s = null;
        s.toString();//这里会发生空指针异常,程序执行到这里JVM会在底层new一个NullPointerException对象
    }
}

2.异常继承结构

在这里插入图片描述

  1. 所有的异常和错误都是可抛出的。都继承了Throwable类。
  2. Error是无法处理的,出现后只有一个结果:JVM终止。
  3. Exception是可以处理的。
  4. Exception的分类:
    ①所有的RuntimeException的子类:运行时异常/未检查异常(UncheckedException)/非受控异常
    ②Exception的子类(除RuntimeException之外):编译时异常/检查异常(CheckedException)/受控异常
  5. 编译时异常和运行时异常区别:
    ①编译时异常特点:在编译阶段必须提前处理,如果不处理编译器报错。
    ②运行时异常特点:在编译阶段可以选择处理,也可以不处理,没有硬性要求。
    ③编译时异常一般是由外部环境或外在条件引起的,如网络故障、磁盘空间不足、文件找不到等
    ④运行时异常一般是由程序员的错误引起的,并且不需要强制进行异常处理。

2.1 编译时异常和运行时异常区别

注意:编译时异常并不是在编译阶段发生的异常,所有的异常发生都是在运行阶段的,因为每个异常发生都是会new异常对象的,new异常对象只能在运行阶段完成。那为什么叫做编译时异常呢?这是因为这种异常必须在编译阶段提前预处理,如果不处理编译器报错,因此而得名“编译时异常”。

2.2 如何让异常发生(throw关键字)

package exceptiontest;

public class ExceptionTest02 {
    public static void main(String[] args) {
//        // 异常的发生需要经历2个阶段
//        // 第一个阶段:创建异常对象
//        NullPointerException e = new NullPointerException();
//        // 第二个阶段:让异常发生(手动抛出异常)
//        throw e;

        //将以上两个阶段合并成一步
        throw new NullPointerException();
    }
}

运行结果:
在这里插入图片描述

3.自定义异常

第一步:编写异常类继承Exception或者RuntimeException
第二步:提供一个无参数构造方法,再提供一个带String msg参数的构造方法,在构造方法中调用父类的构造方法。

一个小示例:

①定义两个编译时异常:

  1. IllegalNameException:无效用户名异常
  2. IllegalAgeException:无效年龄异常

②完成如下需求:

  • 编写一个用户注册的方法,该方法接收两个参数,一个是用户名,一个是年龄。如果用户名长度在[6 - 12]位,并且年龄大于18岁时,输出用户注册成功。
  • 如果用户名长度不是[6 - 12]位时,让程序出现异常,让IllegalNameException异常发生!
  • 如果年龄小于18岁时,让程序出现异常,让IllegalAgeException异常发生!

示例代码:

package exceptiontest.exception;

/**
 * 自定义无效用户名异常:当用户名长度小于6位或者大于12位的,认为程序出现了异常
 */
public class IllegalNameException extends Exception {

    public IllegalNameException() {
    }

    public IllegalNameException(String message) {
        super(message);
    }
}
package exceptiontest.exception;

/**
 * 自定义无效年龄异常:当年龄小于18岁,认为程序出现了异常
 */
public class IllegalAgeException extends Exception {

    public IllegalAgeException() {
    }

    public IllegalAgeException(String message) {
        super(message);
    }
}
package exceptiontest.exception;

import javax.sound.midi.Soundbank;
import java.util.Scanner;

/**
 * 编写一个用户注册的方法,该方法接收两个参数,一个是用户名,一个是年龄。
 * 如果用户名长度在[6 - 12]位,并且年龄大于18岁时,输出用户注册成功。
 * 如果用户名长度不是[6 - 12]位时,让程序出现异常,让IllegalNameException异常发生!
 * 如果年龄小于18岁时,让程序出现异常,让IllegalAgeException异常发生!
 */
public class ExceptionTest03 {
    public static void main(String[] args) {
        System.out.println("欢迎来到用户管理系统,请先注册:");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.next();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        UserServise userServise = new UserServise();
        userServise.register(name, age);
    }
}

/**
 *用户的业务类
 */

class UserServise{
    public void register(String name, int age){
        System.out.println("正在注册[" + name + "],请稍后......");
        UserDao userDao = new UserDao();
        userDao(name, age);
        System.out.println("注册成功,欢迎[" + name + "]");
    }
}

/**
 * 操作数据库的一个类
 * 用户需要注册,其用户名和年龄是需要保存的
 */
class UserDao{
    public void save(String name, int age){
        System.out.println("用户[" + name + "]的信息正在保存...");
        if(name.length() < 6 || name.length()>12){
            throw  new IllegalNameException();
        }
        if(age < 18){
            throw new IllegalAgeException();
        }
        System.out.println("用户[" + name + "]的信息保存成功!");

    }
}

但是以上代码在throw new IllegalNameException();IllegalAgeException会报错,因为定义的异常继承的是Exception,是编译时异常,需要对其进行处理,没有处理编译器自然会报错。

4.异常的处理

  • 异常的处理包括两种方式:
    ①声明异常:类似于推卸责任的处理方式。在方法定义时使用throws关键字声明异常,告知调用者,调用这个方法可能会出现异常。这种处理方式的态度是:如果出现了异常则会抛给调用者来处理。
    ②捕捉异常:真正的处理捕捉异常。在可能出现异常的代码上使用try...catch进行捕捉处理。这种处理方式的态度是:把异常抓住。其它方法如果调用这个方法,对于调用者来说是不知道这个异常发生的。因为这个异常被抓住并处理掉了。
  • 异常在处理的整个过程中应该是:声明和捕捉联合使用。若产生异常的位置不捕捉,向上抛出异常,总需要有一个上层调用者捕捉掉,最差是直接抛到main方法中,交给JVM处理。
  • 什么时候捕捉?什么时候声明?
    如果异常发生后需要调用者来处理的,需要调用者知道的,则采用声明方式。否则采用捕捉。

4.1 第一种处理方式:声明异常 (throws关键字)

  • 如果一个异常发生后希望调用者来处理的,使用声明异常(俗话说:交给上级处理)
    public void m() throws AException, BException... {}
  • 如果AExceptionBException都继承了XException,那么也可以这样写:
    public void m() throws XException{}
  • 调用者在调用m()方法时,编译器会检测到该方法上用throws声明了异常,表示可能会抛出异常,编译器会继续检测该异常是否为编译时异常,如果为编译时异常则必须在编译阶段进行处理,如果不处理编译器就会报错。
  • 如果所有位置都采用throws,包括main方法的处理态度也是throws,如果运行时出现了异常,最终异常是抛给了main方法的调用者(JVM),JVM则会终止程序的执行。因此为了保证程序在出现异常后不被中断,至少main方法不要再使用throws进行声明了。
  • 发生异常后,在发生异常的位置上,往下的代码是不会执行的,除非进行了异常的捕捉。

上述例子若使用throws关键字:

package exceptiontest.exception;

import java.util.Scanner;

/**
 *第一种处理方式:声明异常 (throws关键字)
 */
public class ExceptionTest03 {
    public static void main(String[] args) throws IllegalAgeException, IllegalNameException { //向上throws异常,交给JVM处理,即程序中止,产生报错
        System.out.println("欢迎来到用户管理系统,请先注册:");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.next();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        UserServise userServise = new UserServise();
        userServise.register(name, age); //这里的代码有可能出现异常,出现了异常之后,后续程序不再执行
        System.out.println("main over!");
    }
}

/**
 *用户的业务类
 */

class UserServise{
    public void register(String name, int age) throws IllegalAgeException, IllegalNameException {//向上throws异常
        System.out.println("正在注册[" + name + "],请稍后......");
        UserDao userDao = new UserDao();
        userDao.save(name, age); //这里的代码有可能出现异常,出现了异常之后,后续程序不再执行
        System.out.println("注册成功,欢迎[" + name + "]");
    }
}
/**
 * 操作数据库的一个类
 * 用户需要注册,其用户名和年龄是需要保存的
 */
class UserDao{
    public void save(String name, int age) throws IllegalNameException, IllegalAgeException { //向上throws异常
        System.out.println("用户[" + name + "]的信息正在保存...");
        if(name.length() < 6 || name.length()>12){
            throw new IllegalNameException(); //若程序执行到这产生了异常,则后续代码不再执行
            //这里不能写任何代码,因为这里的代码永远不会执行
        }
        if(age < 18){
            throw new IllegalAgeException();
        }
        System.out.println("用户[" + name + "]的信息保存成功!");
    }
}

运行结果:

  1. 没有异常:
    在这里插入图片描述
  2. name无效:
    在这里插入图片描述
  3. nameAge都无效(只抛出IllegalNameException异常,因为程序执行到throw new IllegalNameException();就不再往下执行了):
    在这里插入图片描述
  4. age无效:
    在这里插入图片描述

4.2 第二种处理方式:捕捉异常 (try…catch…关键字)

如果一个异常发生后,不需要调用者知道,也不需要调用者来处理,选择使用捕捉方式处理。

try{
// 尝试执行可能会出现异常的代码
// try块中的代码如果执行出现异常,出现异常的位置往下的代码是不会执行的,直接进入catch块执行
}catch(AException e){
// 如果捕捉到AException类型的异常,在这里处理
}catch(BException e){
// 如果捕捉到BException类型的异常,在这里处理
}catch(XException e){
// 如果捕捉到XException类型的异常,在这里处理
}
// 当try..catch..将所有发生的异常捕捉后,这里的代码是会继续往下执行的。

上述例子若使用try...catch...关键字:

package exceptiontest.exception.trycatchtest;

import exceptiontest.exception.IllegalAgeException;
import exceptiontest.exception.IllegalNameException;

import java.util.Scanner;

/**
 * 第二种处理方式:捕捉异常 (try...catch...关键字)
 */
public class ExceptionTest04 {
    public static void main(String[] args) {
        System.out.println("欢迎来到用户管理系统,请先注册:");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.next();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        UserServise userServise = new UserServise();
        try {
            userServise.register(name, age);
            System.out.println("如果以上行的代码出现异常,这里的代码不会执行!");
        } catch (IllegalAgeException e) {
            System.out.println("对不起,年龄不合法!");
        } catch (IllegalNameException e) {
            System.out.println("对不起,用户名不合法!");
        }
        System.out.println("main over!");

    }
}

class UserServise{
    public void register(String name, int age) throws IllegalAgeException, IllegalNameException { //这里可以try...catch,也可以throws,一般系统是要在前端有所提示,所以这里依旧选择throws
        System.out.println("正在注册[" + name + "],请稍后......");
        UserDao userDao = new UserDao();
        userDao.save(name, age);

        System.out.println("注册成功,欢迎[" + name + "]");

    }
}

class UserDao{
    public void save(String name, int age) throws IllegalNameException, IllegalAgeException { //throw new异常的位置一定都是搭配throws,因为产生的异常是需要传递出去的,不能自己产生自己就try...catch...捕捉处理了,这是没有意义的,所以这里使用throws向上抛
        System.out.println("用户[" + name + "]的信息正在保存...");
        if(name.length() < 6 || name.length()>12){
            throw  new IllegalNameException();
        }
        if(age < 18){
            throw new IllegalAgeException();
        }
        System.out.println("用户[" + name + "]的信息保存成功!");
    }
}

运行结果:

  1. 没有异常(同上)

  2. name无效:
    在这里插入图片描述

  3. nameAge都无效(只提示用户名不合法,因为程序先判断的name,并throw new IllegalNameException();,就直接被对应的catch分支捕捉处理了):
    在这里插入图片描述

  4. age无效:
    在这里插入图片描述

4.2.1 catch可以写多个,并且遵循自上而下,从小到大(其可以看作是分支,最多只有一个catch会被执行)

如果catch时从大到小:

 try {
	userServise.register(name, age);
    System.out.println("如果以上行的代码出现异常,这里的代码不会执行!");
 }catch (Exception e){
     
 } catch (IllegalAgeException e) {
     System.out.println("对不起,年龄不合法!");
 } catch (IllegalNameException e) {
     System.out.println("对不起,用户名不合法!");
 }

直接编译报错:
在这里插入图片描述

4.2.2 Java7新特性:catch后面小括号中可以编写多个异常,使用运算符“|”隔开。

try {
	userServise.register(name, age);
	System.out.println("如果以上行的代码出现异常,这里的代码不会执行!");
} catch (IllegalAgeException | IllegalNameException e) { //注意这里只有最后有一个e,|前面没有
	System.out.println("对不起,年龄或名字不合法!");
}

运行结果:
在这里插入图片描述
当多个异常的处理方式一样的时候,推荐同时处理;若处理方式不一样(像上面),还是建议分开处理(细粒度更明确)!
同时注意:该用法所处理的异常必须是没有继承关系的,否则报错

5.异常的使用

  1. 自定义异常的使用:
package exceptiontest;

import exceptiontest.exception.IllegalAgeException;

public class ExceptionTest05 {
    public static void main(String[] args) {
        User user  = new User();
        user.setName("zhangsan");
        try { //try...catch...捕捉异常
            user.setAge(-1);
        } catch (IllegalAgeException e) {
            System.out.println("年龄不合法!");
        }
    }
}

class User{
    private String name;
    private int age;

    public User() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) throws IllegalAgeException { //产生异常的位置使用throw将异常抛出
        if(age < 0 || age > 120){ //对于年龄进行异常处理
            throw new IllegalAgeException();
        }
        this.age = age;
    }
}

运行结果:
在这里插入图片描述
2. JDK内置的异常的使用:

package exceptiontest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ExceptionTest06 {
    public static void main(String[] args) {
            m1();
    }

    public static void m1(){
        try {  //try...catch...捕捉
            m2();
        } catch (FileNotFoundException e) {
            System.out.println("文件没有找到!");
        }
    }

    public static void m2() throws FileNotFoundException {  //向上抛出
        FileInputStream in = new FileInputStream("D://Tools/a.txt"); //FileInputStream 类 throws FileNotFoundException,所以需要进行对应的异常处理

    }
}

在这里插入图片描述

6.异常的常用方法

  • 获取异常的简单描述信息:
    exception.getMessage();获取的message是通过构造方法创建异常对象时传递过去的String message
  • 打印异常堆栈信息(帮助程序员调试程序,更推荐):
    exception.printStackTrace();
  • 要会看异常的堆栈信息:
    异常信息的打印是符合栈数据结构的。
    看异常信息主要看最开始的描述信息,即看栈顶信息。

exception.getMessage();示例代码:

package exceptiontest.exception.trycatchtest02;

import exceptiontest.exception.IllegalAgeException;
import exceptiontest.exception.IllegalNameException;

import java.util.Scanner;

/**
 * 异常的常用方法一:exception.getMessage()
 */
public class ExceptionTest07 {
    public static void main(String[] args) {
        System.out.println("欢迎来到用户管理系统,请先注册:");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.next();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        UserServise userServise = new UserServise();
        try {
            userServise.register(name, age);
        } catch (IllegalAgeException e) {
            System.out.println(e.getMessage()); //e.getMessage()返回 《throw new IllegalAgeException("年龄不合法,应该大于18岁!");》中传入的信息
        }catch (IllegalNameException e){
            System.out.println(e.getMessage()); //同上理
        }
        System.out.println("main over!");
    }
}

class UserServise{
    public void register(String name, int age) throws IllegalAgeException, IllegalNameException { //这里可以try...catch,也可以throws,一般系统是要在前端有所提示,所以这里依旧选择throws
        System.out.println("正在注册[" + name + "],请稍后......");
        UserDao userDao = new UserDao();
        userDao.save(name, age);

        System.out.println("注册成功,欢迎[" + name + "]");
    }
}

class UserDao{
    public void save(String name, int age) throws IllegalNameException, IllegalAgeException { //throw new异常的位置一定都是搭配throws,向上throws异常
        System.out.println("用户[" + name + "]的信息正在保存...");
        if(name.length() < 6 || name.length()>12){
            throw new IllegalNameException("用户名不合法,长度应该在6-12位!");
        }
        if(age < 18){
            throw new IllegalAgeException("年龄不合法,应该大于18岁!");
        }
        System.out.println("用户[" + name + "]的信息保存成功!");
    }
}

IllegalNameExceptionIllegalAgeException两个异常类同前面代码。

运行结果:
在这里插入图片描述
exception.printStackTrace();示例代码:

package exceptiontest.exception.trycatchtest02;

import exceptiontest.exception.IllegalAgeException;
import exceptiontest.exception.IllegalNameException;

import java.util.Scanner;

/**
 * 异常的常用方法一:exception.printStackTrace()
 */
public class ExceptionTest07 {
    public static void main(String[] args) {
        System.out.println("欢迎来到用户管理系统,请先注册:");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.next();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        UserServise userServise = new UserServise();
        try {
            userServise.register(name, age);
        } catch (IllegalAgeException e) {
            e.printStackTrace(); //打印异常堆栈信息
        }catch (IllegalNameException e){
            e.printStackTrace(); //打印异常堆栈信息
        }
        //try...catch后依旧会执行
        System.out.println("main over!");
    }
}

class UserServise{
    public void register(String name, int age) throws IllegalAgeException, IllegalNameException { //这里可以try...catch,也可以throws,一般系统是要在前端有所提示,所以这里依旧选择throws
        System.out.println("正在注册[" + name + "],请稍后......");
        UserDao userDao = new UserDao();
        userDao.save(name, age);

        System.out.println("注册成功,欢迎[" + name + "]");
    }
}

class UserDao{
    public void save(String name, int age) throws IllegalNameException, IllegalAgeException { //throw new异常的位置一定都是搭配throws,向上throws异常
        System.out.println("用户[" + name + "]的信息正在保存...");
        if(name.length() < 6 || name.length()>12){
            throw new IllegalNameException("用户名不合法,长度应该在6-12位!");
        }
        if(age < 18){
            throw new IllegalAgeException("年龄不合法,应该大于18岁!");
        }
        System.out.println("用户[" + name + "]的信息保存成功!");
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述
注意:出现main over!在不同位置输出是因为高版本的JDK使用了多线程并发,处理异常的是另一个线程。

7.finally语句块

  • finally语句块中的代码是一定会执行的。
  • finally语句块不能单独使用,至少需要配合try语句块一起使用:
    ①try…finally
    ②try…catch…finally
  • 通常在finally语句块中完成资源的释放(比如IO流,对文件读写管道的关闭),资源释放的工作比较重要,如果资源没有释放会一直占用内存。为了保证资源的关闭,也就是说:不管程序是否出现异常,关闭资源的代码一定要保证执行。因此在finally语句块中通常进行资源的释放。

7.1 finally的初步使用

  1. finally中的代码一定会执行:
package exceptiontest.finallytest;

public class ExceptionTest08 {
    public static void main(String[] args) {
        try{
            String s = null;
            s.toString();
        }finally {
            System.out.println("finally 中的 main over"); //即使上述程序发生异常,finally语句块中的代码都一定会执行!

        }
        System.out.println("main over"); //由于没有catch,上述程序发生异常后,直接中止,不会执行到这里
    }
}

运行结果:
在这里插入图片描述
2. 使用IO流的示例代码(finally中释放资源):

package exceptiontest.finallytest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest09 {
    public static void main(String[] args) {
        FileInputStream in = null;
        try {
            in = new FileInputStream("D:\\workspace\\IDEAProjects\\Java_se\\src\\exceptiontest\\finallytest\\ExceptionTest08.java");
            //开始读
            byte[] bytes = new byte[1024]; //一次读取1KB
            int readCount = 0;
            while ((readCount =in.read(bytes))!=-1){ //in.read(bytes))获取到每次读取的长度,赋给readCount
                System.out.println(new String(bytes, 0, readCount)); //将每次读取到的内容输出
                //in.close(); //要是关闭流的操作放在这里,一旦上述程序出现异常,则该行代码无法执行到,资源无法释放,会一直占用内存 
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            //关闭流释放资源,为保证其一定执行,将其放到finally语句块中
            if (in != null) { //先判断其是否为空
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果(输出读到的文件内容):
在这里插入图片描述

7.2 final、finally、finalize分别是什么?

①final是一个关键字,修饰的类无法继承,修饰的方法无法覆盖,修饰的变量不能修改。
②finally是一个关键字,使用在异常处理机制中,必须联合try一起使用,finally语句块中的代码一定会执行。
③finalize是一个标识符,它是Object类中的一个方法,是由垃圾回收期GC负责调用的。

7.3 finally相关面试题

  1. 以下程序执行结果是什么?
public static void main(String[] args) {
  // 程序执行结果是?
    System.out.println(get());
}

public static boolean get(){
    try{
        return true;
    }finally {
        return false;
    }
}

结果为false,finally语句块一定会执行,在try的 return true;之前,执行finally代码块中的内容,返回false

注意:由于在上面已经return了,所以下面的位置不能写任何代码,否则编译报错:
在这里插入图片描述

  1. 以下程序执行结果是什么?
public static void main(String[] args) {
    // 程序执行结果是?
    System.out.println(get());
}

public static int get(){
    int i = 0;
    try{
        return i;
    }finally {
        i++;
        System.out.println(i);
    }
}

finally语句块中的代码一定会执行,所以i++后先输出1,由于Java中遵循代码自上而下执行的规则,所以try中return i;时输出的是i++之前的状态,以下是反编译之后的效果:

public static int get(){
    int i = 0;
    int j = i;
    i++;
    return j;
}

所以最后返回的i依旧为0,所以有结果:
在这里插入图片描述

  1. 以下程序执行结果是什么?
public static void main(String[] args) {
    // 程序执行结果是?
    try{
        System.out.println("try...");
        return;
    }finally {
        System.out.println("finally...");
    }
}

finally语句块中的代码一定会执行,在try中的return;之前就执行了finally语句块中的代码,所以结果为:
在这里插入图片描述

  1. 以下程序执行结果是什么?
public static void main(String[] args) {
  // 程序执行结果是?
    System.out.println("返回:" + get());
}

public static int get(){
    try{
        System.out.println("try...");
        return 1;
    }finally {
        System.out.println("finally...");
    }
}

同上,finally语句块中的代码一定会执行,在try中的return;之前就执行了finally语句块中的代码,所以结果为:
在这里插入图片描述

  1. 以下程序执行结果是什么?
package exceptiontest.finallytest;

public class ExceptionTest10 {
    public static void main(String[] args) {
        // 程序执行结果是?
        try{
            System.out.println("try...");
            System.exit(0); //退出JVM
        }finally {
            System.out.println("finally...");
        }
    }
}

System.exit(0);是退出JVM,此时finally语句块中代码无法执行了,所以结果为:
在这里插入图片描述

  1. 以下程序执行结果是什么?
public static void main(String[] args) {
    // 程序执行结果是?
    System.out.println("返回:" + get());
}

public static int get(){
    try{
        System.out.println("try...");
        System.exit(0); //退出JVM
    }finally {
        System.out.println("finally...");
    }
    return 1;
}

同上System.exit(0);是退出JVM,所以 return 1;虽然没有报错,但是实际上是永远执行不到的,所以结果为:
在这里插入图片描述
7. 补充一个s++++s相关的

public static void main(String[] args) {
    int s = 20;
    s++;
    System.out.println(s); 
    s = s++;
    System.out.println(s);
    s= ++s;
    System.out.println(s);
}

输出结果为:
21
21
22
最开始 s++;即s自增1,此时s=21而后s = s++;是先执行s赋值给s,此时s++并没有让s自增1,此时s=21,而最后的s= ++s;是先让让s自增1后,再将新的值赋给s,所以此时s=22

8.方法覆盖与异常

原则:方法覆盖之后,不能比父类方法抛出更多的异常,可以更少。

  • 不能更多(编译报错):
    在这里插入图片描述
  • 可以更少:
    在这里插入图片描述

在这里插入图片描述

注意:
对于运行时异常,可以不用遵循上述原则,父类不抛出异常,子类可以抛出RuntimeException。但实际上开发不会说父类方法抛出的异常和子类覆盖的方法抛出不同异常!一般都会保持一致!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/469754.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Go语言之函数、方法、接口

一、函数 函数的基本语法&#xff1a; func 函数名&#xff08;形参列表&#xff09;&#xff08;返回值列表&#xff09; {执行语句...return 返回值列表 } 1.形参列表&#xff1a;表示函数的输入 2.函数中的语句&#xff1a;表示为了实现某一功能的代码块 3.函数可以有返回…

SpringBoot集成WebService

1&#xff09;添加依赖 <dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-spring-boot-starter-jaxws</artifactId><version>3.3.4</version><exclusions><exclusion><groupId>javax.validation<…

[蓝桥杯 2023 省 B] 飞机降落(暴搜DFS+贪心)

总结&#xff1a;为什么你看到题想不出来怎么写呢&#xff0c;我想不到这道题还会用到dfs的思想&#xff0c;顶多能知道可能会有贪心&#xff0c;还是得多做题。 这道题让我想起来导弹拦截和借教室&#xff0c;记得有空做做&#xff01;&#xff01;不要研究难题&#xff0c;把…

蓝桥杯--完全二叉树

import java.util.Scanner;import static java.lang.Math.log;public class top9 {//求树的每一层的和public static void main(String [] args){Scanner scannernew Scanner(System.in);int nscanner.nextInt();int [] arrnew int[n];for(int i0;i<n;i){arr[i]scanner.next…

超快速排序(蓝桥杯,归并排序,acwing)

题目描述&#xff1a; 在这个问题中&#xff0c;您必须分析特定的排序算法----超快速排序。 该算法通过交换两个相邻的序列元素来处理 n 个不同整数的序列&#xff0c;直到序列按升序排序。 对于输入序列 9 1 0 5 4&#xff0c;超快速排序生成输出 0 1 4 5 9。 您的任务是确…

英伟达深夜放王炸|字节跳动游戏之路波折不断|文旅短剧风口将至|25岁QQ魅力不减,5亿人在用|云计算市场疯长152%|电商巨头齐瞄向富足悠闲银发族

新闻一分钟速览 文旅短剧风口将至&#xff0c;一地狂拍十部&#xff0c;影视界看法分歧&#xff0c;悬念丛生&#xff01;字节跳动游戏之路波折不断&#xff0c;能否逆风翻盘引关注。折叠屏手机痛症治愈&#xff0c;实力席卷高端市场&#xff0c;势头强劲&#xff01;雷军豪言…

12|检索增强生成:通过RAG助力鲜花运营

什么是 RAG&#xff1f;其全称为 Retrieval-Augmented Generation&#xff0c;即检索增强生成&#xff0c;它结合了检 索和生成的能力&#xff0c;为文本序列生成任务引入外部知识。RAG 将传统的语言生成模型与大规模 的外部知识库相结合&#xff0c;使模型在生成响应或文本时可…

014 Linux_同步

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;Linux &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多操作系统知识 文章目录 前言一、死锁&#xff08;1&#xff09;死锁概念 二、同步&#xff08;1&#xff09;同步概念&#xff…

Python入门(小白友好)

知识图谱 搭建环境 安装Python:Download Python | Python.org 安装PyCharm:Download PyCharm: The Python IDE for data science and web development by JetBrains 注意:专业版本是收费的,新手小白使用社区版(community)即可 创建第一个项目: 一些PyCharm的设置(也适用…

40年创新蝶变,IBM与中国共创新质生产力

2024年是“新质生产力”进入政府工作报告第一年&#xff0c;也是百年追求科技创新的IBM在华40周年&#xff0c;同时IBM全球正全力打造下一代企业生产力平台——突破性的企业混合云与AI。2023年&#xff0c;IBM推出基于开源混合云平台Red Hat Openshift的下一代企业级数据和AI平…

显隐特征融合的指静脉识别网络

文章目录 显隐特征融合的指静脉识别网络总结摘要介绍显隐式特征融合网络(EIFNet)掩膜生成模块(MGM)掩膜特征提取模块(MFEM)内容特征提取模块(CFEM)特征融合模块(FFM) THUFVS实验和结果数据集实现细节评估掩膜生成模型消融实验FFM模块门控层Batch Size损失函数超参数选择 论文 …

Python学习从0到1 day17 Python异常、模块、包

不走心的努力&#xff0c;都是在敷衍自己 ——24.3.19 万字长文&#xff0c;讲解异常、模块、包&#xff0c;看这一篇就足够啦 什么是异常? 当检测到一个错误时&#xff0c;python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的异常&am…

解决重装系统之后,开始菜单找不到Anaconda3相关图标

一、anaconda3安装后在开始菜单找不到&#xff0c;如下图所示 二、进入Anaconda3安装的位置 在安装位置按住shift键鼠标右键&#xff0c;打开poworshell&#xff0c;输入 start cmd最后的结果如图。

联发科MT8797迅鲲1300T规格参数_MTK5G安卓核心板方案定制

联发科MT8797&#xff08;迅鲲1300T&#xff09;平台采用Arm Cortex-A78和Cortex-A55组成的八核架构CPU&#xff0c;以及Arm Mali-G77MC9九核GPU&#xff0c;集成了AI处理器MediaTek APU&#xff0c;支持5G Sub-6GHz全频段和5G双载波聚合,支持1.08亿像素拍照和多镜头组合,以及1…

docker入门(五)—— 小练习,docker安装nginx、elasticsearch

练习 docker 安装 nginx # 搜素镜像 [rootiZbp15293q8kgzhur7n6kvZ home]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx …

模拟面试

1.TCP通信中的三次握手和四次挥手过程 三次握手 1.客户端像向服务器端发送连接请求 2.服务器应答连接请求 3.客户端与服务器简历连接 四次挥手&#xff1a; 客户端或服务器端发起断开请求,这里假设客户端发送断开请求 1.客户端向服务器发送断开请求 2.服务器应答断开请求 3.服…

c++类和对象(中)类的6个默认成员函数及const成员函数

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;类和对象 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱们之前也是…

OCP NVME SSD规范解读-13.Self-test自检要求

4.10节Device Self-test Requirements详细描述了数据中心NVMe SSD自检的要求&#xff0c;这一部分规范了设备自身进行各种健康检查和故障检测的过程。自检对于确保SSD的正常运行和提前预防潜在故障至关重要。 在进行设备自检时&#xff0c;设备应当确保不对用户数据造成破坏&am…

Unity类银河恶魔城学习记录11-2 p104 Inventoty源代码

此章节相对较难理解&#xff0c;有时间单独出一章讲一下 Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili InventoryItem.cs…

三维指静脉生物识别成像设备设计和多视图验证研究

文章目录 三维指静脉生物识别成像设备设计和多视图验证研究总结摘要介绍多视角指静脉识别模型结构内容特征编码Transformer(CFET)主导特征选择模块(DFSM) 实验和结果数据集实施细节视角研究池化层的作用消融实验和SOTA方法比较 论文: Study of 3D Finger Vein Biometrics on I…