详述try-catch-fianlly

本文深入讲解Java中的异常概念,包括异常的定义、后果、结构、分类及处理方式,重点介绍了try/catch/finally的使用,并探讨了异常处理的弊端及解决方案,通过引入log4j实现更高效的日志记录。

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

1、什么叫异常

下面来看一段代码

public class Test {
    public static void main(String[] args) {
        System.out.println("111");
        System.out.println(1/0);
    }
}

我们知道在分式中0不能做分母,但编译时代码并没有报错,运行时出现了这样的提示

这就是异常——Java语言将程序运行过程中所发生的不正常严重错误称为异常

2、异常的后果

     如果出现异常的话,会中断正在运行的程序,同级代码不再运行,例如

public class Test {
    public static void main(String[] args) {
        System.out.println("111");
        System.out.println(1/0);
        System.out.println("222");
    }
}

结果显示:

可以看到“222”这行代码没有被运行,所以说“异常”中断了程序的运行

3、异常的结构

Throwable中常用方法: public String getMessage():获取异常信息;

                                       public void printStackTrace():输出异常堆栈中的异常信息

(可以被其所有子类(Exception、Error及其子类)直接调用)

Exception中构造方法: public Exception():无参构造方法;

                                      public Exception(String message):可以指定详细异常信息的有参构造方法;

(可以Exception及其子类直接调用)

Throwable是最大的一类,是所有异常和错误的父类。Throwable有两个直接子类Exception(异常)和Error(错误)。

Error : 指合理的应用程序在执行过程中发生的严重问题。当程序发生这种严重错误时,通常的做法是通知用户并中止程序的执行。

Exception:指异常。出现异常可以我们可以进行异常处理。

4、异常的分类

异常分为运行时异常(RuntimeException)和非运行时异常即检查时异常(CheckedException)。

运行时异常:可以不显式对异常的处理,javac依然可以编译程序,如下图(1/0),写代码时并没有出错,但运行时会出错

处理异常办法:选中异常那一行代码,然后右击——Surround with——try/catch Block

检查时异常:必须显式对异常的处理,不然javac不会对程序进行编译,如下图

怎么办呢?

将鼠标放到波浪线处,会出现   

第一种方式就是添加throws  declaration,直接点击就行,目的是将异常交给JVM去处理

第二种方式就是用try/catch,直接点击下面的Surround with try/catch即可

(需要注意的是:异常是代码正确的前提下异常,如果代码本身就错,那就是错误,如Class.fonam(),代码本身就写错了,这不是异常)

5、异常处理方式(try/catch/finally)

先看一段代码

public class Test {
    public static void main(String[] args) {
        String name=null;
        System.out.println(name.length());
    }
}

结果会显示空指针异常

所以如果再来一行代码的话,不会执行,因为程序已中断运行

public class Test {
    public static void main(String[] args) {
        String name=null;
        System.out.println(name.length());
        System.out.println("0");//不会执行
    }
}

try/catch中try是尝试运行,如果出现异常,就会catch,捕捉异常,类似于if...else  if...else  if...else...

public class Test {
    public static void main(String[] args) {
    	try {
            String name=null;
            System.out.println(name.length());
            System.out.println(1/0);
            Integer.parseInt("QQQQ");
        }catch(NullPointerException e) {
            System.out.println("NUll");
        }catch(ArithmeticException e) {
            System.out.println("0");
        }catch(Exception e) {//Exception是所有异常的父类
            System.out.println("other"+e);
		}
    }
}

catch(),括号里前面的单词的是异常类型,e是异常对象,如果不清楚异常类型就用Exception,因为它是所有异常的父类,类似于上转型。根据异常类型执行相应的语句,如

因为第一个name就异常了 ,所以name以下代码就中断运行了,而name是空指针异常,所以执行第一个catch里的语句。

再如最后那个异常,如图

注意:catch里的异常类型要按从小到大的顺序写,不能第一个就写Exception,因为Exception是所有异常父类,如果第一个就写Exception,那所有的异常都属于这一类,这以下的catch就没用了。当然第一个catch也不能是RuntimeException,因为它是所有运行时异常的父类,范围太大。

try/catch/finally

一个try可以有多个catch,但try不允许单独使用

try/catch上面已用过,不再赘述,下面看与finally搭配

finally 无论try中是否有异常发生,finlly中的代码总会执行,一般用于释放资源

try可以单独与finally搭配

try也可以同时与catch、finally搭配

6、异常处理方式的弊端及其解决方式

先看以下代码

可以看到,无法找到1,异常信息太多

弊端是:将异常信息打印到控制台——>存入一段缓存,缓存有大小——>当缓存满了,但是异常信息源源不断,则会将最先进入缓存的异常信息移除(因为堆是先进先出)——>意味着无法全面的发现程序运行期间出现的问题——>为了全面收集系统运行期间出现的所有异常信息,log4j诞生了——>将所有异常信息输出到一个文件中——因为文件在硬盘上——>可以认为无限大

Log4j是Apache的一个开源项目,通过使用Log4j,可以控制日志信息格式及其输送目的地(控制台、文件、数据库等),方便后期查找系统运行期间出现的问题,进而便于维护系统。

步骤:

第一步:导入log4j-1.2.15.jar依赖包;

①在项目中右击——new——folder,创建一个名为 “lib” 的folder,

②将log4j-1.2.15.jar依赖包拷贝到lib中,然后选中log4j-1.2.15.jar依赖包,右击——Build Path——Add...(后面单词没记清),导入成功

第二步:在src根目录下创建名为log4j.properties的文件,文件内容如下:
 

# DEBUG设置输出日志级别,由于为DEBUG,所以ERROR、WARN和INFO 级别日志信息也会显示出来 log4j.rootLogger=DEBUG,Console,RollingFile 

#将日志信息输出到控制台

log4j.appender.Console=org.apache.log4j.ConsoleAppender 

log4j.appender.Console.layout=org.apache.log4j.PatternLayout 

log4j.appender.Console.layout.ConversionPattern= [%-5p]-[%d{yyyy-MM-dd HH:mm:ss}] -%l -%m%n

#将日志信息输出到操作系统D盘根目录下的log.log文件中 

log4j.appender.RollingFile =org.apache.log4j.DailyRollingFileAppender 

log4j.appender.RollingFile.File=D://log.log 

log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout

log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p %-40.40c %X{traceId}-%m%n

第三步:src目录创建Test类,代码如下:

import org.apache.log4j.Logger;
 
public class Test {
 
	private static final Logger logger = Logger.getLogger(Test.class);
 
	public static void main(String[] args) {
		try {
			Class.forName("ErrorClassName");
		} catch (ClassNotFoundException e) {
			logger.debug(e.getMessage(),e);//详细日报信息
			logger.info(e.getMessage(),e);//详细日报信息
			logger.warn(e.getMessage());//简单日报信息
			logger.error(e.getMessage());//简单日报信息
		}
          }
}

经过上述三步,最终Java工程结构如下:

运行Test类方法,打开D盘根目录中log.log文件可以看到相应的日志信息,此时的日志信息都会显示出来,Log4j常用日志级别从高到低依次为:ERROR、WARN、INFO和DEBUG,由于上例所设置的Log4j日志级别为DEBUG,所以ERROR、WARN和INFO 级别的日志信息也会显示出来。

间歇性产生新日志文件

上例配置文件是将所有的日志信息都收集到了一个文件中,那么随着时间的推移,该文件会越来越大,内容也会越来越多,这不利于后期对日志文件进行分析,为了解决该问题可以这样配置log4j.properties文件:

# DEBUG设置输出日志级别,由于为DEBUG,所以ERROR、WARN和INFO 级别日志信息也会显示出来
log4j.rootLogger=DEBUG,RollingFile
#每天产生一个日志文件(RollingFile)  
log4j.appender.RollingFile=org.apache.log4j.DailyRollingFileAppender
#当天的日志文件全路径
log4j.appender.RollingFile.File=d:/logs/sirius.log
#服务器启动日志是追加,false:服务器启动后会生成日志文件把老的覆盖掉
log4j.appender.RollingFile.Append=true
#日志文件格式  
log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout  
log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p %-40.40c %X{traceId}-%m%n
log4j.appender.RollingFile.Threshold=DEBUG
#设置每天生成一个文件名后添加的名称,备份名称:sirius.log.年月日时分.log
log4j.appender.RollingFile.DatePattern='.'yyyy-MM-dd-HH-mm'.log'

DatePattern选项的有效值为:

'.'yyyy-MM,对应monthly(每月)

'.'yyyy-ww,对应weekly(每周)

'.'yyyy-MM-dd,对应daily(每天)

'.'yyyy-MM-dd-a,对应half-daily(每半天)

'.'yyyy-MM-dd-HH,对应hourly(每小时)

'.'yyyy-MM-dd-HH-mm,对应minutely(每分钟)

DatePattern中不用处理的文字要放到单引号(')中,如上面的(.)。

 

 

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值