①请写出常见的5个异常?
②异常的继承体系?
③异常分为哪两种类型, 区别是什么?
什么是异常
从一个代码讲起?
package exception;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
input.close();
System.out.println("========执行后续代码=======");
}
}
如果用户输入错误, 输入的非正常的数据, 理想状态是代码还可以继续运行.生活中我们遇到异常要进行处理, 处理之后要继续生活下去.
java中的异常: 程序执行过程中出现的非正常现象.
如何表示异常的概念
java面向对象的编程语言, 所以java也对异常进行了抽象, 以OOP的方式处理异常. 用类描述异常.
Excetion 类表示所有的可以处理的异常的父类.
public class Exception{
private String message;
public Exception(String msg){
this.message = msg;
}
public void printInfo(){
}
}

说明:
所有异常的根类是Throwable , 两个子类: Error 表示错误, 不是程序可以处理的错误.一些硬件原因无法进行处理.
第2个子类是: Exception : 异常, 这些异常是可以通过代码处理的.
如何进行异常处理
如何处理异常, 台风来了, 处理的机制, 警告: 红色警告, 橙色的警告; 启动三级应急响应机制. 这些应急机制其实就是异常处理. java也提供一套应急处理机制. 来处理java程序出现的异常, 以保障代码可以正常运行,而不至于崩溃, 中断执行.该套机制包括如下几个关键字:
try : try 试一试 , 表示该块代码可能出现异常, 我们试一试执行. try不能独立存在,必须有个伙伴
catch: 抓捕,捕获, 捕获出现的异常, 你可以理解为摄像头, 抓拍出现违章的车辆. 北京某高速一个摄像头,创收上亿.
finally: 最终的, 不管是否出现异常都执行的业务代码.
throw: 手动抛出异常,
throws: 声明一个方法抛出异常.
try-catch
包括三种情况:
①不出现异常, 正常执行
package exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(InputMismatchException me) {
String message = me.getMessage();
System.out.println("出现异常:"+message);
}
input.close();
System.out.println("========执行后续代码=======");
}
}
cache代码块不执行, 程序继续执行下面的业务代码.
②出现异常, catch可以捕获异常
package exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(InputMismatchException me) {
String message = me.getMessage();
System.out.println("出现异常:"+message);
}
input.close();
System.out.println("========执行后续代码=======");
}
}
输入字母,出现InputMismatchException异常, 出现的异常类型和捕获的异常类型一致,或者是捕获异常类型的子类. catch代码块执行.
③出现异常,catch捕获的异常和出现的异常不匹配
package exception;
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(ArrayIndexOutOfBoundsException me) {
String message = me.getMessage();
System.out.println("出现异常:"+message);
me.printStackTrace();
}
input.close();
System.out.println("========执行后续代码=======");
}
}
代码中断执行, catch代码块不执行.
try跟多个catch
package exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo5 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(ArithmeticException me) {
String message = me.getMessage();
System.out.println("出现算术异常:"+message);
me.printStackTrace();
}catch(InputMismatchException e) {
System.out.println("输入的数据不一致, 请输入数字.");
e.printStackTrace();
}catch(NullPointerException e) {
System.out.println("出现控制针异常.....");
e.printStackTrace();
}
input.close();
System.out.println("========执行后续代码=======");
}
}
以上写法可以捕获多种异常,一般为了安全起见, 有可能出现未知异常; 建议在最后加上Exception捕获异常 . Exception是所有异常的父类,意味着可以捕获所有异常. 但是他的位置一定要放在最后: 由特殊到一般.由子类到父类.
package exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo6 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(ArithmeticException me) {
String message = me.getMessage();
System.out.println("出现算术异常:"+message);
me.printStackTrace();
}catch(InputMismatchException e) {
System.out.println("输入的数据不一致, 请输入数字.");
e.printStackTrace();
}catch(NullPointerException e) {
System.out.println("出现控制针异常.....");
e.printStackTrace();
}catch(Exception e) {
System.out.println("出现异常: "+e.getMessage());
}
input.close();
System.out.println("========执行后续代码=======");
}
}
异常处理的代码比业务代码还要多, 所以从jdk1.7引入一个写的写法;用来 简化异常处理的代码.
package exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo7 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(ArithmeticException|InputMismatchException|NullPointerException e) { System.out.println("出现算术或者输入不匹配或空指针异常: "+e.getMessage());
}catch(Exception e) {
System.out.println("出现未知异常: "+e.getMessage());
e.printStackTrace();
}
input.close();
System.out.println("========执行后续代码=======");
}
}
try-catch-finally
比较完整的异常处理机制.
finally表示最终的, 不管是否出现异常都执行的代码块.
一般用在文件读写, 数据库访问; 不管是否出现异常都要执行: 譬如关闭文件流, 关闭数据库连接.
package exception;
import java.util.Scanner;
public class Demo8 {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
try {
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int num3 = num1 / num2;
System.out.println(num3);
}catch(Exception me) {
String message = me.getMessage();
System.out.println("出现异常:"+message);
me.printStackTrace();
}finally {
input.close();
System.out.println("===执行finally代码块==");
}
System.out.println("========执行后续代码=======");
}
}
try-finally
finally 可以出现 0 次或 1 次.
package exception;
import java.io.File;
public class Demo9 {
public static void main(String[] args) {
try {
File file =new File("x:\\abc");
} finally {
System.out.println("===finally==");
}
}
}
throw和throws
throw手动抛出异常: 我不处理异常, 抛给我的调用者,
throws是声明方法抛出的异常: 可以提示方法的调用者,我的方法有可能出现异常, 里面埋有地雷,你要处理掉. throws的方法处理方式有两种:
package exception;
public class Product {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) throws Exception {
if(price <0 || price >10000) {
throw new Exception("价格不能小于0或者不能超过10000");
}else {
this.price = price;
}
}
}
①: 处理异常
package exception;
public class ProductTest {
public static void main(String[] args) {
Product pro = new Product();
try {
pro.setPrice(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
②:不处理, 继续抛出异常
package exception;
public class ProductTest2 {
public static void main(String[] args) throws Exception{
Product pro = new Product();
pro.setPrice(-1);
}
}
如果在main方法抛出异常, 直接由JVM处理.
常见的异常
package exception;
import java.util.Date;
public class Demo4 {
public static void main(String[] args) {
Date date = new Date();
System.out.println( (java.sql.Date)date );
}
}
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.NullPointerException
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
自定义异常
自定义异常: 公司的项目根据业务需要自定义业务异常类. 自定义异常类要继承Exception, 编写相应的构造方法.
package exception;
public class PriceException extends Exception{
private static final long serialVersionUID = 1L;
public PriceException(String msg) {
super(msg);
}
}
package exception;
import java.io.IOException;
public class Product {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) throws PriceException {
if(price <0 || price >10000) {
throw new PriceException("价格不能小于0或者不能超过10000");
}else {
this.price = price;
}
}
protected void print() throws IOException {
System.out.println("xx");
}
}
package exception;
public class ProductTest {
public static void main(String[] args) {
Product pro = new Product();
try {
pro.setPrice(0);
} catch (PriceException e) {
e.printStackTrace();
}
}
}
使用Log4j记录异常
现在代码进行异常处理存在的问题是什么:
异常不能保存 , 输出到控制台, 下次再运行控制台信息被删除. 最好的办法是可以把异常信息存储到文件中, 以方便查询错误信息. 日志记录. 可以输出到控制台,也可以保存到文件;
使用是第三方的组件:log4j 主流的日志记录工具. 如何使用Log4j日志记录工具:
①: 添加log4j 的jar包 log4j-1.2.11.jar
②: 编写日志的配置文件 log4j.properties 属性文件
③: 在类中使用log4j记录日志.
(1) 添加jar包
在项目的目录下创建lib文件; 粘贴到该文件夹, 右键添加到构建路径.
(2) log4j.properties
### 把日志信息输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
### 把日志信息输出到文件 ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
### 设置优先级别、以及输出源 ###
log4j.rootLogger=error, stdout,file
appender: 输出到目的地 ConsoleAppender 控制台, FileAppender 文件目的地 (输出目的地)
stdout: 标准输出流 standard 标准 out输出
layout, ConversionPattern 指定输出的格式和内容:
%d date 日期
%l location 位置
%m message 异常的信息
%n 换行
日志的级别: debug < info < warn < error < fatal (致命的); 如果指定的error那么输出的日志信息是 >=当前级别的. 所以 debug是日志最低级别, 输出的日志也是最多的,
(3)在类中使用Log4j记录日志信息
①创建log对象
private Logger logger = Logger.getLogger(Product.class);
②调用相应级别的方法
package exception;
import java.io.IOException;
import org.apache.log4j.Logger;
public class Product {
private Logger logger = Logger.getLogger(Product.class);
private double price;
public Product() {
logger.debug("====创建商品对象=====");
}
public double getPrice() {
return price;
}
public void setPrice(double price) throws PriceException {
logger.info("===设值商品价格====");
if(price <0 || price >10000) {
logger.error("===设值商品价格异常==="+price);
throw new PriceException("价格不能小于0或者不能超过10000");
}else {
logger.info("===设值商品几个成功===");
this.price = price;
}
}
protected void print() throws IOException {
System.out.println("xx");
}
}
面试题讲解
try-catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序
try-catch- finally块中, finally块唯一不执行的情况是什么?
package exception;
class Calculator{
public int devide(int num1,int num2) {
int num3 = 0;
try {
num3 = num1 / num2;
} catch (ArithmeticException e) {
System.out.println("出现异常: " + e.getMessage());
return num3;
}finally {
num3 = 1000;
System.out.println("==finally==");
}
System.out.println("================");
return num3;
}
}
public class Demo11 {
public static void main(String[] args) {
Calculator c = new Calculator();
int result = c.devide(100, 0);
System.out.println("结果:" + result);
}
}
ide(int num1,int num2) {
int num3 = 0;
try {
num3 = num1 / num2;
} catch (ArithmeticException e) {
System.out.println("出现异常: " + e.getMessage());
return num3;
}finally {
num3 = 1000;
System.out.println("==finally==");
}
System.out.println("================");
return num3;
}
}
public class Demo11 {
public static void main(String[] args) {
Calculator c = new Calculator();
int result = c.devide(100, 0);
System.out.println("结果:" + result);
}
}