当前位置: 首页 > news >正文

javaSE(从0开始)day14

目录

Exception异常处理:

异常的基本概念

一、java异常:

1、方法一:约定返回错误码。例如,处理一个文件,如果返回0,表示成功,返回其他整数,表示约定的错误码:

2、方法二:在语言层面上提供一个异常处理机制。Java内置了一套异常处理机制,总是使用异常来表示错误。异常是一种class,因此它本身带有类型信息。异常可以在任何地方抛出,但只需要在上层捕获,这样就和方法调用分离了:

3、异常的种类:首先分为error(严重错误不是人为的)和Exception(异常):

4、异常又分为运行时异常和编译异常:

(1)运行时异常:非必要处理异常

(1.1)java.lang.NullPointerException: 空指针异常

(1.2) StringIndexOutOfBoundsException:下标越界异常

(1.3)java.lang.ArrayIndexOutOfBoundsException:数组下标越界

(1.4)java.lang.ArithmeticException:算术异常(除0异常)

(1.5)java.lang.NumberFormatException:格式异常

(1.6)ClassCastException:类型转换异常

 (2)编译时异常:IOException   UnsupportedEncodingException....除运行异常外都是编译异常

二、捕获异常:

1、捕获异常:必须处理异常(会报错)捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:

2、多个catch 语句:可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。简单地说就是:多个catch语句只有一个能被执行。try块中可以放法多个异常代码,并且异常无关联,处理机制不同 ,try块出现异常,会跳转导对应的catch块,执行catch块中的内容,执行完成后,不会再返回到原出现异常的部分,进行下面的内容 ,异常后的代码不会执行。

3、finally代码块:无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,怎么写?可以把执行语句写若干遍:正常执行的放到try中,每个catch再写一遍。例如:

(1)finally特点:

(1.1)finally语句不是必须的,可写可不写;

(1.2)finally总是最后执行。

4、注意事项:

(1)多个异常进行捕获需要注意顺序问题

(2)Catch捕获时自上而下进行异常的匹配,越是顶级的类,越要放到下面,写法遂循先子后父 /

(3) 再不然把多余的catch省略

三、抛出异常:

1、抛出异常的两种方式:

(1) throws声明异常: throws:声明异常,在方法上声明可能会出现的异常类型

(2)throw  抛出异常: throw:扔出异常对象,放在方法体内,一般和if判断配合使用 

2、异常的传递:当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个try ... catch被捕获为止。

 3、异常的转换:在捕获异常的时候catch代码块里面又出现了一个新的异常,将新的异常信息传递给旧的异常信息。

4、异常的屏蔽:如果在执行finally语句时抛出异常,那么,catch语句的异常不能抛出原本的异常,会将finally代码块中得新异常信息抛出,原本的异常将不被打印出来:

四、自定义异常:

        在Java中除了核心类库给我们万宁的异常类之外,我们还可以定义自己所需要格式得自定义异常类在一个大型项目中,可以自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。一个常见的做法是自定义一个BaseException作为“根异常”,然后,派生出各种业务类型的异常。BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:

五、使用Log4j:

1、使用Log4j的好处:

(1)可以设置输出级别,禁止某些级别输出。例如,只输出错误日志;

(2)可以被重定向到文件,这样可以在程序运行结束后查看日志;

(3)可以按包名控制日志级别,只输出某些包打的日志;

(4)可以规范项目开发;

2、使用Log4j输出的目的地:

(1)console:输出到屏幕;

(2)file:输出到文件;

(3)socket:通过网络输出到远程计算机;

(4)jdbc:输出到数据库

3、Log4j的日志级别:在Loggers(记录器)组件中,级别分6种:TRACE、DEBUG、INFO、WARN、ERROR和FATAL。

4、Log4j的应用:

(1)添加依赖:

     (1.1)把从Apache官网下载。下载并解压后,将下面1个jar包加入项目的classpath中commons-logging-1.2.jar

      (1.2)我们需要从Apache官网下载Log4j,解压后,把以下3个jar包放到classpath中:

(2)项目下创建lib文件夹 (与src同级),复制jar包到目录下,在将依赖导入项目依赖中

(3)创建log4j配置:在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。例如,仅输出ERROR级别的日志。最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。上述结构虽然复杂,但我们在实际使用的时候,并不需要关心Log4j的API,而是通过配置文件来配置它。虽然配置Log4j比较繁琐,但一旦配置完成,使用起来就非常方便。对上面的配置文件,凡是INFO级别的日志,会自动输出到屏幕,而ERROR级别的日志,不但会输出到屏幕,还会同时输出到文件。并且,一旦日志文件达到指定大小(1MB),Log4j就会自动切割新的日志文件,并最多保留10份。

(4)Log4j使用:第一步,通过LogFactory获取Log类的实例; 第二步,使用Log实例的方法打日志。

(1.1)在静态方法中引用Log,通常直接定义一个静态类型变量:

(1.2)在实例方法中引用Log,通常定义一个实例变量:

(1.3)在子类中使用父类实例化的log:


Exception异常处理:

在编程中,Exception(异常)是指程序运行过程中发生的意外情况或错误,这些情况会中断程序的正常执行流程。处理异常是编写健壮程序的重要部分。

异常的基本概念

  • 异常类型:不同的错误对应不同的异常类型,例如文件未找到(FileNotFoundError)、除以零(ZeroDivisionError)等
  • 异常处理:通过特定语法捕获并处理异常,防止程序崩溃
  • 异常传递:如果异常未被捕获,会向上传递,直到被捕获或导致程序终止

一、java异常:

     在计算机程序运行的过程中,总是会出现各种各样的错误。有一些错误是用户造成的,比如,希望用户输入一个int类型的年龄,但是用户的输入是abc

调用方如何获知调用失败的信息?有两种方法:

1、方法一:约定返回错误码。例如,处理一个文件,如果返回0,表示成功,返回其他整数,表示约定的错误码:

int code = processFile("C:\\test.txt");
if (code == 0) {// ok:
} else {// error:switch (code) {case 1:// file not found:case 2:// no read permission:default:// unknown error:}
}

2、方法二:在语言层面上提供一个异常处理机制。Java内置了一套异常处理机制,总是使用异常来表示错误。异常是一种class,因此它本身带有类型信息。异常可以在任何地方抛出,但只需要在上层捕获,这样就和方法调用分离了:

try {String s = processFile(“C:\\test.txt”);// ok:
} catch (FileNotFoundException e) {// file not found:
} catch (SecurityException e) {// no read permission:
} catch (IOException e) {// io error:
} catch (Exception e) {// other error:
}

3、异常的种类:首先分为error(严重错误不是人为的)和Exception(异常):

4、异常又分为运行时异常和编译异常:

(1)运行时异常:非必要处理异常
(1.1)java.lang.NullPointerException: 空指针异常

String str=null;

System.out.println(str.length());

(1.2) StringIndexOutOfBoundsException:下标越界异常

String str1="hello";

System.out.println(str1.charAt(5));

(1.3)java.lang.ArrayIndexOutOfBoundsException:数组下标越界

int[] arr=new int[0];
System.out.println(arr[0]);

(1.4)java.lang.ArithmeticException:算术异常(除0异常)

int Number =10/0;

System.out.println(Number);

(1.5)java.lang.NumberFormatException:格式异常

java.lang.NumberFormatException ;

int number=Integer.parseInt("f24");

System.out.println(number);

(1.6)ClassCastException:类型转换异常

Demo01 aa=(Demo01) (new Object());

System.out.println(aa);

 (2)编译时异常:IOException   UnsupportedEncodingException....除运行异常外都是编译异常

二、捕获异常:

1、捕获异常:必须处理异常(会报错)捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:

public class Main {public static void main(String[] args) {byte[] bs = toGBK("中文");System.out.println(Arrays.toString(bs));}static byte[] toGBK(String s) {try {// 用指定编码转换String为byte[]:return s.getBytes("GBK");} catch (UnsupportedEncodingException e) {// 如果系统不支持GBK编码,会捕获到UnsupportedEncodingException:System.out.println(e); // 打印异常信息return s.getBytes(); // 尝试使用用默认编码}}
}

2、多个catch 语句:可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。简单地说就是:多个catch语句只有一个能被执行。try块中可以放法多个异常代码,并且异常无关联,处理机制不同 ,try块出现异常,会跳转导对应的catch块,执行catch块中的内容,执行完成后,不会再返回到原出现异常的部分,进行下面的内容 ,异常后的代码不会执行。

public class Demo04 {public static void main(String[] args) {try {process1("123");process2(6);process3("hello你", "GBK");} catch (NumberFormatException ex) {ex.printStackTrace();System.out.println("方法1出错");} catch (IndexOutOfBoundsException ex) {ex.printStackTrace();System.out.println("方法2出错");} catch (UnsupportedEncodingException ex) {ex.printStackTrace();System.out.println("方法3出错");}
//可使用短路或|连接try {
//            process1("123");
//            process2(2);
//            process3("hello你", "GBK");
//        } catch (NumberFormatException |IndexOutOfBoundsException|UnsupportedEncodingException ex) {
//            ex.printStackTrace();
//            System.out.println("异常了");
//
//        }}//NumberFormatExceptionprivate static void process1(String s) {int number = Integer.parseInt(s);System.out.println(number);}//可能会有下表越界private static void process2(int index) {int[] arr = {1, 2, 3, 4, 5};System.out.println(arr[index]);}//次方阿飞可能会有UnsupportedEncodingException这类异常//属于编译时异常,必须要进行异常的处理和异常的捕获private static void process3(String str, String charSet) throws UnsupportedEncodingException {byte[] bytes = str.getBytes(charSet);System.out.println(Arrays.toString(bytes));}
}

3、finally代码块:无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,怎么写?可以把执行语句写若干遍:正常执行的放到try中,每个catch再写一遍。例如:

public static void main(String[] args) {try {process1();process2();process3();System.out.println("END");} catch (UnsupportedEncodingException e) {System.out.println("Bad encoding");System.out.println("END");} catch (IOException e) {System.out.println("IO error");System.out.println("END");}
}

上述代码无论是否发生异常,都会执行System.out.println("END");这条语句。那么如何消除这些重复的代码?Java的try ... catch机制还提供了finally语句,finally语句块保证有无错误都会执行。上述代码可以改写如下:

public static void main(String[] args) {try {process1();process2();process3();} catch (UnsupportedEncodingException e) {System.out.println("Bad encoding");} catch (IOException e) {System.out.println("IO error");} finally {System.out.println("END");}
}
(1)finally特点:
(1.1)finally语句不是必须的,可写可不写;
(1.2)finally总是最后执行。

如果没有发生异常,就正常执行try { ... }语句块,然后执行finally。如果发生了异常,就中断执行try { ... }语句块,然后跳转执行匹配的catch语句块,最后执行finally。可见,finally是用来保证一些代码必须执行的。

某些情况下,可以没有catch,只使用try ... finally结构。

void process(String file) throws IOException {
    try {
        ...
    } finally {
        System.out.println("END");
    }
}

4、注意事项:

(1)多个异常进行捕获需要注意顺序问题
(2)Catch捕获时自上而下进行异常的匹配,越是顶级的类,越要放到下面,写法遂循先子后父 /
(3) 再不然把多余的catch省略

三、抛出异常:

1、抛出异常的两种方式:

(1) throws声明异常: throws:声明异常,在方法上声明可能会出现的异常类型
    public static int divide1(int a,int b)throws ArithmeticException{return a/b;}
(2)throw  抛出异常: throw:扔出异常对象,放在方法体内,一般和if判断配合使用 
 //throw扔出编译异常外象,在方法上必须要声明此类的异常public static void process(String str) throws UnsupportedEncodingException, NullPointerException {if (str == null) {throw new NullPointerException("str为null了,请注意査");}if (!("6Bk".equalsIgnoreCase(str) || "uTF-8".equalsIgnoreCase(str))) {throw new UnsupportedEncodingException(str + "不符合编格式");};System.out.println(str);}

2、异常的传递:当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个try ... catch被捕获为止。

public class Main {public static void main(String[] args) {try {process1();} catch (Exception e) {e.printStackTrace();}}static void process1() {process2();}static void process2() {Integer.parseInt(null); // 会抛出NumberFormatException}
}

java.lang.NumberFormatException: null
    at java.base/java.lang.Integer.parseInt(Integer.java:614)
    at java.base/java.lang.Integer.parseInt(Integer.java:770)
    at Main.process2(Main.java:16)
    at Main.process1(Main.java:12)
    at Main.main(Main.java:5)

printStackTrace()对于调试错误非常有用,上述信息表示:NumberFormatException是在java.lang.Integer.parseInt方法中被抛出的,从下往上看,调用层次依次是:

  1. main()调用process1()
  2. process1()调用process2()
  3. process2()调用Integer.parseInt(String)
  4. Integer.parseInt(String)调用Integer.parseInt(String, int);

 3、异常的转换:在捕获异常的时候catch代码块里面又出现了一个新的异常,将新的异常信息传递给旧的异常信息。

public class Demo04 {public static void main(String[] args) {try {process1();} catch (Exception e) {e.printStackTrace();}System.out.println("end");}private static void process1() {try {process2();} catch (Exception e) {throw new IllegalArgumentException("参数不合法",e);}finally {System.out.println("end process1");}}private static void process2() {Integer.parseInt(null);}
}

4、异常的屏蔽:如果在执行finally语句时抛出异常,那么,catch语句的异常不能抛出原本的异常,会将finally代码块中得新异常信息抛出,原本的异常将不被打印出来:

public class Main {public static void main(String[] args) {try {Integer.parseInt("abc");} catch (Exception e) {System.out.println("catched");throw new RuntimeException(e);} finally {System.out.println("finally");throw new IllegalArgumentException();}}
}

       这说明finally抛出异常后,原来在catch中准备抛出的异常就“消失”了,因为只能抛出一个异常。没有被抛出的异常称为“被屏蔽”的异常(Suppressed Exception)。在极少数的情况下,我们需要获知所有的异常。如何保存所有的异常信息?方法是先用origin变量保存原始异常,然后调用Throwable.addSuppressed(),把原始异常添加进来,最后在finally抛出:

public class Main {public static void main(String[] args) throws Exception {Exception origin = null;try {System.out.println(Integer.parseInt("abc"));} catch (Exception e) {origin = e;throw e;} finally {Exception e = new IllegalArgumentException();if (origin != null) {e.addSuppressed(origin);}throw e;}}
}

四、自定义异常:

        在Java中除了核心类库给我们万宁的异常类之外,我们还可以定义自己所需要格式得自定义异常类在一个大型项目中,可以自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。一个常见的做法是自定义一个BaseException作为“根异常”,然后,派生出各种业务类型的异常。BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:

 class BaseException extends RuntimeException{public BaseException() {}public BaseException(String message) {super(message);}public BaseException(String message, Throwable cause) {super(message, cause);}public BaseException(Throwable cause) {super(cause);}}
class OrderTimeOutException extends BaseException {public OrderTimeOutException(String message) {super(message);}
}public class Demo02{public static void main(String[] args) {checkOrderTime("0001",LocalDate.of(2025,07,12));}public static void checkOrderTime(String orderId,LocalDate orderDate){
//        if(LocalDate.now().minusDays(3).isBefore(orderDate)){if(LocalDate.now().getDayOfYear()-orderDate.getDayOfYear()<=3){System.out.println("未超时");}else {throw new OrderTimeOutException("订单超时:订单号"+orderId);}}
}

异常信息:

Exception in thread "main" com.yuan.myexception.OrderTimeOutException: 订单超时:订单号0001
    at com.yuan.myexception.Demo02.checkOrderTime(Order.java:16)
    at com.yuan.myexception.Demo02.main(Order.java:9)

五、使用Log4j:

Log4j 是一种非常流行的日志框架,Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别日志要输出的地方日志以何种形式输出

综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。Log4j 的架构大致如下:

1、使用Log4j的好处:

(1)可以设置输出级别,禁止某些级别输出。例如,只输出错误日志;
(2)可以被重定向到文件,这样可以在程序运行结束后查看日志;
(3)可以按包名控制日志级别,只输出某些包打的日志;
(4)可以规范项目开发;

2、使用Log4j输出的目的地:

(1)console:输出到屏幕;
(2)file:输出到文件;
(3)socket:通过网络输出到远程计算机;
(4)jdbc:输出到数据库

3、Log4j的日志级别:在Loggers(记录器)组件中,级别分6种:TRACEDEBUGINFOWARNERRORFATAL

级别是有顺序的:TRACE<DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度,明白这一点很重要,Log4j有一个规则:只输出级别不低于设定级别的日志信息

假设Loggers级别设定为INFO,则INFOWARNERRORFATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。

4、Log4j的应用:

(1)添加依赖:
     (1.1)把从Apache官网下载。下载并解压后,将下面1个jar包加入项目的classpathcommons-logging-1.2.jar
      (1.2)我们需要从Apache官网下载Log4j,解压后,把以下3个jar包放到classpath中:
  • log4j-api-2.x.jar

  • log4j-core-2.x.jar

  • log4j-jcl-2.x.jar
(2)项目下创建lib文件夹 (与src同级),复制jar包到目录下,在将依赖导入项目依赖中
(3)创建log4j配置:在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。例如,仅输出ERROR级别的日志。最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。上述结构虽然复杂,但我们在实际使用的时候,并不需要关心Log4j的API,而是通过配置文件来配置它。虽然配置Log4j比较繁琐,但一旦配置完成,使用起来就非常方便。对上面的配置文件,凡是INFO级别的日志,会自动输出到屏幕,而ERROR级别的日志,不但会输出到屏幕,还会同时输出到文件。并且,一旦日志文件达到指定大小(1MB),Log4j就会自动切割新的日志文件,并最多保留10份。
(4)Log4j使用:第一步,通过LogFactory获取Log类的实例; 第二步,使用Log实例的方法打日志。
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class Main {public static void main(String[] args) {Log log = LogFactory.getLog(Main.class);log.trace("trace");//追踪级别log.debug("debug");//调试级别log.info("info");//普通信息log.warn("warn");//警告log.error("error");//错误级别log.fatal("fatal");//致命错误}}
(1.1)在静态方法中引用Log,通常直接定义一个静态类型变量:
// 在静态方法中引用Log:
public class Main {static final Log log = LogFactory.getLog(Main.class);static void foo() {log.info("foo");}
}
(1.2)在实例方法中引用Log,通常定义一个实例变量:
// 在实例方法中引用Log:
public class Person {protected final Log log = LogFactory.getLog(getClass());void foo() {log.info("foo");}
}
(1.3)在子类中使用父类实例化的log:
// 在子类中使用父类实例化的log:
public class Student extends Person {void bar() {log.info("bar");}
}

http://www.lryc.cn/news/596741.html

相关文章:

  • 数据交换---JSON格式
  • C语言:第11天笔记
  • JavaScript 02 数据类型和运算符数组对象
  • numpy库 降维,矩阵创建与元素的选取,修改
  • 生成式人工智能展望报告-欧盟-01-引言
  • Vue开发常用
  • 2025 年最新 AI 技术:全景洞察与深度解析​
  • 操作系统:系统调用(System Calls)
  • 深入理解程序链接机制:静态链接、ELF加载与动态库实现原理
  • 计算机底层入门 05 汇编学习环境通用寄存器内存
  • [LLM]Synthetic Visual Genome
  • gflags使用
  • 【锁】MySQL中有哪几种锁?
  • 【C语言进阶】动态内存管理(1)
  • Claude Code Kimi K2 环境配置指南 (Windows/macOS/Ubuntu)
  • NumPy库使用教学,简单详细。
  • 一些Avalonia与WPF内容的对应关系和不同用法
  • numpy的详细知识点,简单易懂
  • 【Linux系统】基础IO
  • HTTP 协议常见字段(请求头/响应头)
  • 【初识数据结构】CS61B 中的堆以及堆排序算法
  • 数据库设计mysql篇
  • 第六章 工具调用
  • linux辅助知识(Shell 脚本编程)
  • 基于LangGraph的Open Deep Research架构全解析:从多Agent协作到企业级落地
  • 元宇宙游戏与VR的关联性及发展分析(截至2025年7月)
  • 工业互联网时代,如何通过混合SD-WAN提升煤炭行业智能化网络安全
  • 【上市公司变量测量】Python+FactSet Revere全球供应链数据库,测度供应链断裂与重构变量——丁浩员等(2024)《经济研究》复现
  • Spring之【Bean工厂后置处理器】
  • 从重复劳动到自动化:火语言 RPA 的实践与思考