异常

异常

1.了解异常概念

2.理解java异常处理机制

3.会捕捉异常

1.异常概念

(1)前面所遇到的异常(类型Class):

  • ArrayIndexOutOfBoundsException 数组下标越界异常
  • NullPointerException (NPE) 空指针异常 当引用数据类型没有引用某个内存空间时 它的值就是null,那么如果null值去使用方法、属性则会报出此异常
  • ClassCastException 类型转换异常 多态时尤其可能出现,不确定多态的具体类型时 转换可能会出现问题。
  • ClassNotFoundException 类找不到异常
  • ArithmeticException 算术异常 除数为0
  • InputMismatchException 输入不匹配异常

(2) 异常的含义

a.异常:在执行某件事的过程中,出现了不符合预期的情况

如:电梯异常、地铁异常、电路异常…

b.程序中的异常:

在程序运行过程中出现的问题,会导致程序中断结束(异常)

2.理解java异常处理机制

java提供了一套异常处理机制来解决我们使用过多的if判断问题(补不全、代码维护性变差、阅读困难)

关于异常的关键词:

try:尝试

catch:抓住

finally:最终的

**throw:**扔

**throws:**扔

3.捕捉异常的语句

3.1 try—catch组合

// 在try代码块中执行有可能出现异常的代码段
// 当出现了异常的情况下,catch(异常类型)标注的异常会捕获合适的异常(如果代码出现了catch里面的异常类型就会捕获)
// 捕获到合适的异常之后,可以对异常采取修复/处理手段
// 代码可以继续正常的执行下去
try{
    // 可能会出现异常的代码
}catch(异常类型){
    // 对异常的修复/处理
}


/*
执行流程:
	在执行try块代码时
		当出现:InputMismatchException情况时,会立刻结束try块代码,JVM会帮你构建一个异常对象(nextInt()代码中有此源码) new InputMismatchException(nfe.getMessage()); 
		然后我们的catch块就可以捕获到此异常 形参会接收此对象引用,进行正常处理,处理完继续正常运行。
		
		当出现:ArithmeticException情况时,会立刻结束try块代码,JVM会帮你创建的异常对象,无法被catch块所接收,相当于方法的形参和实参不一致,所以catch不会捕获异常,JVM会将你的异常直接以堆栈跟踪的形式打印出来,并且会结束我们的程序
*/
Scanner input = new Scanner(System.in);
try {
    // 可能出现问题的代码
    System.out.print("请输入第一个整数:");
    int num1 = input.nextInt();
    System.out.print("请输入第二个整数:");
    int num2 = input.nextInt();
    // 计算除法
    int num3 = num1 / num2;
    System.out.println(num1+"/"+num2+"="+num3);
}catch(InputMismatchException e) { // 能捕获的异常类型
    System.out.println("对不起!请输入整数!");
}
System.out.println("程序结束!");

3.2多重catch块

// 类似于多重if一样,出现的异常会挨个进行尝试调用catch 只要有一个匹配 则执行处理 后面的catch不会处理了
// 小心异常类型范围大的记得放在后面
try{
	// 可能出现问题的代码
}catch(异常类型1){
	// 对应的处理代码
}catch(异常类型2){
	// 对应的处理代码
}.....
catch(Exception e){ // Exception是异常的顶级父类 它可以接收任何异常类型的对象  (多态)
    // 最终默认的处理代码
}


Scanner input = new Scanner(System.in);
try {
    // 可能出现问题的代码
    System.out.print("请输入第一个整数:");
    int num1 = input.nextInt();
    System.out.print("请输入第二个整数:");
    int num2 = input.nextInt();
    // 计算除法
    int num3 = num1 / num2;
    System.out.println(num1+"/"+num2+"="+num3);
}catch(InputMismatchException e) { // 能捕获的异常类型
    System.out.println("对不起!请输入整数!");
}catch (ArithmeticException e) {
    System.out.println("对不起!除数不能为0!");
}catch (Exception e) {
    System.out.println("服务器繁忙!");
}
System.out.println("程序结束!");



Scanner input = new Scanner(System.in);try {    // 可能出现问题的代码    System.out.print("请输入第一个整数:");  
    int num1 = input.nextInt();   
    System.out.print("请输入第二个整数:"); 
    int num2 = input.nextInt();    
    // 计算除法   
    int num3 = num1 / num2;    System.out.println(num1+"/"+num2+"="+num3);   
     // 一般用于多种需要的处理手段一致的情况下会采用
}
catch(InputMismatchException  | ArithmeticException e) {
    // 能捕获的异常类型   
    // System.err.println("异常出现了!"+e.getMessage());
    e.printStackTrace(); 
    // 打印异常的堆栈跟踪
}System.out.println("程序结束!");


catch代码块中是用于处理异常情况,一般情况下有下方几种手段:

  1. 以友好的形式,提示异常信息System.out.println(); System.err.println(); // 打印红字
  2. 使用异常的堆栈跟踪来打印异常信息(这个和JVM处理不一样,JVM会中断程序)
  3. 使用日志记录异常信息
  4. 根据逻辑进行合理值更改

3.3 try-catch-finally/try-finally

try {

}catch(异常类型 e){
//  处理异常的代码段
}finally{
//  最终执行的的代码段:无论是否出现异常 此处代码段都会被执行
// 一般的应用在资源释放上 io即输入输出 数据以流的形式输入输出
}
try{
// 可能出现的异常的代码
}finally{
// 最终执行的代码:资源释放...
}

面试题1:如果finally和return同时出现,那么如何执行?

会先执行finally中的内容,然后再执行return。

面试题2:final、finally、finalize的区别

  • final的作用

    • 修饰变量则称为常量,常量只允许赋值一次
    • 修饰类则类将无法被继承
    • 修饰方法则方法无法被重写
  • finally的作用

    • 是异常处理中的一个概念,表示无论是否出现异常,finally中的内容都会执行
  • finalize的作用

    • 它是Object类中的一个方法,是Java的GC(垃圾回收器)自动会调用的一个方法。

    • 用法:protected void finalize() throws Throwable { }
      

4.会抛出异常

用throw和throws的关键字

throw和throws的区别

throw 表示抛出异常 抛出异常后面要跟随异常的对象,用于告知调用者异常的信息(异常对象)后期常用来抛出自定义异常。

// 摘自:java.util.Scanner.nextInt()方法
try {
    String s = next(integerPattern());
    if (matcher.group(SIMPLE_GROUP_INDEX) == null)
        s = processIntegerToken(s);
    return Integer.parseInt(s, radix);    
}
// 数值格式转换异常
catch (NumberFormatException nfe) {
    position = matcher.start(); // don't skip bad token
    throw new InputMismatchException(nfe.getMessage());// 抛出异常
}

throws表示声明异常,它是在方法声明上进行指定的,一般表示此方法不会异常处理,最终由调用者统一处理。

例如:

 public FileInputStream(File file) throws FileNotFoundException; 

5.了解异常体系结构

Throwable顶级接口
// 异常指的是可以经过处理而修复的问题  
// 错误是指必须通过修改代码才能修复的问题才能修复的问题
Exception异常的顶级父类                        Error错误的顶级父类:
//OutOfMemory  StackOverFlow

//check异常(受检异常)表示代码编写出来后必须要求提前处理的异常
//例如:FileNotFoundException 
 //unchecked/runtimeException  运行异常(不受检异常): 表示代码编写后非必须要求处理的异常

6.会定义自定义异常

如果觉得java的异常体系不够丰富可以自行创建异常类。.

//public class IllegalAgeException extends Exception{
public class IllegalAgeException extends RuntimeException{

	public IllegalAgeException() {
		super();
	}

	public IllegalAgeException(String message) {
		super(message);
	}
	
}

public void setAge(int age) throws Exception {
    if(age < 0 || age > 100) {
        //			System.out.println("对不起!年龄非法!");
        // throw new Exception("年龄非法!");
        throw new IllegalAgeException("年龄非法!");
    }else {
        this.age = age;
    }
}

7.会使用日志记录异常情况(log4j、log4j2、logback)

logforjava

Int2String

try{

}catch(Exception e){
	// 处理
}

它用来记录系统运行中的一些重要操作信息,便于监视系统运行情况,也便于出现问题后快速找到原因的文件。

.log

我们要记录日志,如果自己来实现这种功能非常繁琐,所以有很多组织或个人开发了相关的工具开源出来供我们使用,那么在我们的Java项目中如何去引用他们编写的这些工具呢?

步骤:

  1. 下载相应的工具包(sdk):他们一般帮助我们将其打成了jar包(压缩包 字节码文件的集合)
  2. 将jar包引入到项目的类库中(像引入jre一样)
  3. 引入之后根据工具的说明书(API文档)进行使用即可

我们记录日志可以采用的工具包:log4j、log4j2、logback…(slfj日志门面)

  • 在Java项目中创建一个文件夹(lib)存放jar包

  • 将jar包引入为类库

    在jar包上右键 -> build path -> add to build path

  • 根据要求和使用说明进行使用

    • 准备一个日志配置文件log4j.properties配置日志运行的规则

      ### 设置Logger输出级别和输出目的地(可以指定多个目的地) ###
      ### 一般在开发的时候使用debug,开发完成后使用error ###
      ### 他们对应的是输出信息的级别,级别越低信息输出越详细,使用debug级别的时候,info中的信息也能输出,使用info的时候,debug对应的信息显示不出来 ###
      ### 日志记录器输出级别:fatal>error>warn>info>debug ###
      ### 后面的两个对应下方的两处 一处打印在控制台 另一处打印在日志文件里
      log4j.rootLogger=debug,console,logFile
      
      ##################################################################################
      ### 把日志信息输出到控制台 ###
      log4j.appender.console=org.apache.log4j.ConsoleAppender
      ### 信息打印到System.err上,红色 ###
      log4j.appender.console.Target=System.out
      ### 指定日志在控制台上输出的布局类型  采用指定格式的类型 ###
      log4j.appender.console.layout=org.apache.log4j.PatternLayout
      ### %r:输出自应用启动到输出该 log信息耗费的毫秒数    %x表示信息输出时左对齐 
      ### %5p:%p表示输出日志信息优先级,即 DEBUG, INFO, WARN, ERROR, FATAL 中间的5控制最小的宽度为5
      ### %F:%L %F:输出日志消息产生时所在的文件名称   %L:输出代码中的行号
      ### %l:输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及行数
      ### %m:输出代码中指定的消息,产生的日志具体信息  %n:输出一个回车换行符, Windows 平台为"\r\n", Unix 平台为"\n"输出日志信息换行
      log4j.appender.console.layout.ConversionPattern= (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
      ##################################################################################
      
      #################################################################################
      ### 把日志信息输出到文件:jbit.log 注意:如果有路径\符号一定要写成\\ 否则会被转义  ###
      log4j.appender.logFile=org.apache.log4j.FileAppender
      ### 指定日志输出的文件名 ###
      log4j.appender.logFile.File=test.log
      ### 指定转换模式 ###
      log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
      ### 指定日志布局类型 ###
      ###log4j.appender.logFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%l %F %p %m%n
      ###log4j.appender.logFile.layout.ConversionPattern= -> (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
      log4j.appender.logFile.layout.ConversionPattern= (%r ms) - %d{yyyy-MM-dd HH:mm:ss}%x[%5p]%l %m%n
      #################################################################################
      
    • 使用API来进行日志记录

      • Logger类

        Logger getLogger(字节码对象);

        • info() 记录普通信息
        • debug() 记录方便我们调试的信息
        • error() 记录错误信息
      public class Demo1 {
      
      	// 								 类名.class
      	static Logger logger = Logger.getLogger(Demo1.class);
      	
      	
      	public static void main(String[] args) {
      		
      		Scanner input = new Scanner(System.in);
      		try {
      			logger.info(">>>>>>程序启动>>>>>>>");
      			// 可能出现问题的代码
      			System.out.print("请输入第一个整数:");
      			int num1 = input.nextInt();
      			logger.info(">>>>>用户正在输入第一个整数,输入的数值为:"+num1+">>>>>>>>");
      			System.out.print("请输入第二个整数:");
      			int num2 = input.nextInt();
      			logger.info(">>>>>用户正在输入第二个整数,输入的数值为:"+num2+">>>>>>>>");
      			// 计算除法
      			int num3 = num1 / num2;
      			logger.info(">>>>>用户正在进行结果计算,结果为:"+num3+">>>>>>>>");
      			System.out.println(num1+"/"+num2+"="+num3);
      		}catch(InputMismatchException e) { // 能捕获的异常类型
      			logger.error(">>>>>>>程序出现输入不匹配异常>>>>>>",e);
      		}catch (ArithmeticException e) {
      			logger.error(">>>>>>>程序出现算术异常>>>>>>",e);
      		}catch (Exception e) {
      			logger.error(">>>>>>>程序出现未知异常>>>>>>",e);
      		}
      		System.out.println("程序结束!");
      		logger.info(">>>>>>程序结束>>>>>>>");
      	}
      
      }
      

="+num3);
}catch(InputMismatchException e) { // 能捕获的异常类型
logger.error(">>>>>>>程序出现输入不匹配异常>>>>>>",e);
}catch (ArithmeticException e) {
logger.error(">>>>>>>程序出现算术异常>>>>>>",e);
}catch (Exception e) {
logger.error(">>>>>>>程序出现未知异常>>>>>>",e);
}
System.out.println(“程序结束!”);
logger.info(">>>>>>程序结束>>>>>>>");
}

}
```

你可能感兴趣的:(异常)