关键词:
目录
1.3.2 采用 finally 释放 Scanner 资源
1.1Java 异常的概念与分类
1.1.1引入异常(数组越界)
public class TestException
/**
* 会出现 ArrayIndexOutOfBoundsException 异常
*/
public void method1()
String names[] = "小凳子", "小椅子", "小桌子";
for (int i = 0; i < 4; i++)
System.out.println(names[i]);
System.out.println("over");
public static void main(String[] args)
TestException te = new TestException();
te.method1();
1.1.2 Throwable
异常的最高父类是 Throwable,在 java.lang 包下。
Throwable 类的构造方法主要有:
-
public Throwable()
构造一个对象,其错误信息串为 null。
-
public Throwable(String message)
构造一个对象,其错误信息串为 message。
Throwable 类的方法主要有:
方法 | 说明 |
---|---|
public String getMessage() | 返回对象的错误信息 |
public void printStackTrace() | 输出对象的跟踪信息到标准错误输出流 |
public void printStackTrace(PrintStream s) | 输出对象的跟踪信息到输出流 s |
public String toString() | 返回对象的简短描述信息 |
Exception 类也有很多的子类,提供我们使用
Throwable 类的子类有 Error 错误和 Exception 违例。Error 错误并不能通过程序代码来解决问题,而 Exception 违例基本是程序员在编写代码时所造成的问题,所以往往我们会将 Error 设为天灾,Exception 设为人祸。
采用判断语句的方式进行异常的处理,首先必须意识到哪些地方可能出现异常,在可能出现异常的地方加入判断语句和处理代码。这种处理方式对程序员的要求高,因为开发者很难列举出所有的异常发生情况,而且代码量大,程序结构相对混乱。对于此类情况,一种较好的解决方案,就是使用异常处理机制。
1.2 Java 异常捕获处理
Java 的异常处理机制中仍体现了面向对象的思想。
- Java 程序的执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给 Java 运行时系统,这个过程称为抛出异常。
- 当 Java 运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获异常。
- 如果 Java 运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的 Java 程序也将退出。
程序员通常只能处理违例 (Exception) ,而对错误 (Error) 无能为力。
异常处理机制中已经明确提出需要有代码来处理该异常,而出现异常,系统会自动生成一个异常类对象,这个异常对象是系统生成的,我们无须创建。
try 和 catch 是关键字,用来处理异常的。该结构中,catch 语句块中一定不要空着,啥都不写,这是一种很危险的情况,如果空着,表示捕获异常,而不做任何处理。
try
// 有异常出现的语句,无异常语句也可以放在这个语句块中
catch(ExceptionClass e)
// 当产生 ExceptionClass 类型异常时的处置代码
catch(ExceptionClass2 e)
// 当产生 ExceptionClass2 类型异常时的处置代码
catch(ExceptionClassN e)
// 当产生 ExceptionClassN 类型异常时的处置代码
]
try 语句块:
- 将可能出现异常的代码都放在 try 代码块中。
- try 语句块中发现异常,剩下的语句将不再执行。
catch 语句块:
- 在 catch 语句块中是对异常对象进行处理的代码。
- 每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常对象。
- 通过 getMessage( ) 获取异常信息或 printStackTrace( ) 跟踪异常信息。
public class TestException
public void method1()
String names[] = "小凳子", "小椅子", "小桌子";
try
for (int i = 0; i < 4; i++)
System.out.println(names[i]);
System.out.println("over");
catch (ArrayIndexOutOfBoundsException e)
System.out.print(e);
public static void main(String[] args)
TestException te = new TestException();
te.method1();
出现异常,系统自动生成 ArrayIndexOutOfBoundsException 异常对象,交给运行时系统,系统去找处理的代码,当匹配到有 catch 的异常是 ArrayIndexOutOfBoundsException 时,就进入 catch 语句块,本次处理方式是打印异常对象,就是调用 toString() 方法返回对象的简短描述信息。使用 catch 语句块,异常对象捕获到一个匹配的 catch ,将不会再考虑其他了
ArithmeticException 数学计算异常(如出现分母为0)
NumberFormatException 数字格式异常(如输入数字时输入字符串)
InputMismatchException 输入不匹配
public class TestException
public void method2(String a,String b)
double c = 0.0;
try
c = Integer.parseInt(a) / Integer.parseInt(b);
catch(ArithmeticException e)
System.out.println(e.getMessage());
catch(NumberFormatException e)
e.printStackTrace();
System.out.println(c);
public static void main(String[] args)
TestException te = new TestException();
te.method2(args[0], args[1]);
最简化的书写方式,也可以这样写,它们都是 Exception 子类。
public class TestException
public void method3(String a,String b)
double c = 0.0;
try
c = Integer.parseInt(a) / Integer.parseInt(b);
catch(Exception e)
System.out.println(e.getMessage());
System.out.println(c);
public static void main(String[] args)
TestException te = new TestException();
te.method3(args[0], args[1]);
1.3 异常处理 finally 语句使用
1.3.1 引入 finally 关键字
之前我们学过的是 final 关键字,而现在需要来学习的 finally 关键字。
finally 关键字主要是和捕获异常的 try-catch 语句一起使用,放在 finally 语句块中的内容表示无条件执行的部分,也就是说不管程序有异常或没有异常都需要执行的部分。
try
// 可能产生异常的代码
catch( ExceptionClass1 e )
// 当产生 ExceptionName1 类型异常时的处置措施
catch( ExceptionClass2 e )
// 当产生ExceptionName2型异常时的处置措施
finally
// 无条件执行的语句
运行时异常:编译的时候都是没有问题,但是运行时会出现异常
RuntimeException 是所有运行时异常的父类,API 如下图:
而实际中有许多都是在编译时会提示需要进行异常处理,否则编译将不能通过。如:
我们可以通过 SimpleDateFormat 类调用 format() 方法来进行日期格式化操作
同时对于以上的代码,我们应该完成转换操作之后,将 SimpleDateFormat 资源进行释放。你就应该要想到的是 finally 语句,无论是否有异常存在,都应该执行的部分,因为它是无条件执行语句块。
企业面试时,经常会提到的问题:final、finally 和 finalize 的区别是什么?
- final 关键字,是用来修饰属性、方法、类的。
- finally 关键字,可以配合异常处理,进行无条件执行操作。
- finalize 不是关键字,是 Object 类中的一个方法,是 Java 垃圾回收机制中进行资源释放的方法。
1.3.2 采用 finally 释放 Scanner 资源
为了避免造成大量的内存占据,我们需要将不在使用的内存空间得到及时的释放。方法结束后,Scanner
对象虽然会进入被回收的队列中,但不是立刻回收,而这会给计算机带来一定的负担。
import java.util.InputMismatchException;
import java.util.Scanner;
public class DivideApples
//苹果数
int appleNum = 0;
//学生数
int stuNum = 0;
public void divide()
System.out.println("**_现在给孩子们分苹果_**");
Scanner input = new Scanner(System.in);
try
System.out.print("请输入桌子上有几个苹果:");
appleNum = input.nextInt();
System.out.print("请输入班上有几个孩子:");
stuNum = input.nextInt();
System.out.println("班上每个孩子分得多少苹果:" + appleNum / stuNum);
System.out.println("孩子们非常开心!");
catch (InputMismatchException e)
System.out.print("苹果数量和孩子人数必须为整数值!");
catch (ArithmeticException e)
System.out.print("孩子人数不能为零!");
finally
input.close();
System.out.print("Scanner 对象进行释放");
public static void main(String[] args)
new DivideApples().divide();
1.3 Java 异常抛出处理
异常的另一种处理方式,便是抛出异常,需要使用关键字 throws 。throws 抛出的异常可以是 0 或多个,也就是说·可以抛出 1 个,或多个。
知道会出现错误直接抛出不处理,由调用该方法的对象处理(try-catch),也可以提醒别人。
public void method2(String a,String b) throws ArithmeticException, NumberFormatException
double c = Integer.parseInt(a) / Integer.parseInt(b);
System.out.println(c);
当然你也可以采用最简化的抛出方式:
public void method3(String a,String b) throws Exception
double c = Integer.parseInt(a) / Integer.parseInt(b);
System.out.println(c);
直接抛出 Exception,就不用一个个的抛出了,当然从规范的角度来说,在企业项目中,还是需要确切到具体的异常类。
public class TestException4
/**
* 采用异常抛出处理方式进行数组下标越界处理
* @throws ArrayIndexOutOfBoundsException 数组下标越界异常
*/
public void method1() throws ArrayIndexOutOfBoundsException
String names[] = "小凳子", "小椅子", "小桌子";
for (int i = 0; i < 4; i++)
System.out.println(names[i]);
System.out.println("over");
/**
* 采用异常抛出处理方式进行数学计算和数字格式化处理
* @param a 命令行参数
* @param b 命令行参数
* @throws ArithmeticException 数学计算异常
* @throws NumberFormatException 数字格式化异常
*/
public void method2(String a,String b) throws ArithmeticException, NumberFormatException
double c = Integer.parseInt(a) / Integer.parseInt(b);
System.out.println(c);
/**
* 采用最简化的方法抛出异常处理
* @param a 命令行参数
* @param b 命令行参数
* @throws Exception 包含了所有的异常
*/
public void method3(String a,String b) throws Exception
double c = Integer.parseInt(a) / Integer.parseInt(b);
System.out.println(c);
public static void main(String[] args)
TestException4 te = new TestException4();
// 调用 method1 方法进行异常处理
try
te.method1();
catch(ArrayIndexOutOfBoundsException e)
System.out.println(e);
// 调用 method2 方法进行异常处理
try
te.method2(args[0], args[1]);
catch (ArithmeticException e)
e.printStackTrace();
catch (NumberFormatException e)
e.printStackTrace();
// 调用 method3 方法进行异常处理
try
te.method3(args[0], args[1]);
catch (Exception e)
e.printStackTrace();
1.3.1 主动抛出异常
之前讲到异常处理机制,当系统发现有异常,会自动产生一个异常对象,然后交给运行时系统,这叫抛出异常;主动抛出异常,那就是不需要系统生成异常对象,而是我们在编写代码时,对于可能会出现异常的部分,自己创建异常对象将它抛出,这就是主动抛出异常。
主动抛出异常,其实是希望提供更明确的异常提示信息。
语法结构:
throw new 异常类(message);
注意:这里是 throw 而不是 throws,有很多同学会搞混 throw 和 throws,你只需要记住一点,throw 关键字后只能抛出一个确切的异常类对象,而 throws 后可以抛出多个异常类,而非 new 的对象。
/**
* 使用 throw 主动抛出异常
*/
public class TestException5
/**
* throw 和 throws 配置使用
* @throws Exception 异常类
*/
public void method1() throws Exception
String names[] = "小凳子", "小椅子", "小桌子";
for (int i = 0; i < 4; i++)
if(i > names.length-1)
throw new ArrayIndexOutOfBoundsException("数组下标越界异常:数组元素提取下标为 " + i + ",超出数组取值范围!");
System.out.println(names[i]);
System.out.println("over");
/**
* throw 和 try-catch 配置使用
* @param a 命令行参数
* @param b 命令行参数
*/
public void method2(String a,String b)
double c = 0.0;
try
int a1 = Integer.parseInt(a);
if(a1 == 0)
throw new RuntimeException("第一个参数为 0 ,除法计算永远都是零");
int b1 = Integer.parseInt(b);
if(b1 == 0)
throw new ArithmeticException("除数不能为零");
c = a1 / b1;
catch(ArithmeticException e)
System.out.println(e);
catch(NumberFormatException e)
e.printStackTrace();
catch(RuntimeException e)
System.out.println(e.getMessage());
System.out.println(c);
public static void main(String[] args)
TestException5 te = new TestException5();
// 调用 mehtod1 方法进行异常处理
try
te.method1();
catch (Exception e)
System.out.println(e.getMessage());
// 调用 method2 方法
te.method2(args[0], args[1]);
方法重写的要求吗?
- 方法名、返回类型、参数列表必须相同。
- 方法的修饰符范围可以相同或更大。
我们可以发现,throws 是不是在方法上声明的,对吧 ~ 🙂
那么方法的重写需要加上第三个要求,抛出的异常要么和父类一样,或是父类抛出异常的子类,但是不能是抛出异常的父类。
父类 ClassA 中的 method() 方法:
public void method() throws ArithmeticException, NumberFormatException
子类 ClassB 中重写父类 method() 方法:
可以只抛出父类中的一个异常类。
public void method() throws ArithmeticException
或是
public void method() throws NumberFormatException
或是
public void method() throws ArithmeticException,NumberFormatException
不抛出异常类也是可以的。
public void method()
但是抛出的异常不能大于父类抛出的异常,则是错误的。
public void method() throws Exception
- 学会使用 throw 和 throws 关键字进行异常操作。
- throws 在方法声明的同时抛出异常,可以到调用方法时再进行处理。
- throw 主动抛出异常对象,可以传递更为确切的异常信息。
- 当子类重写父类方法时,需要考虑抛出的异常类,可以相同或是子类,但是不能更大。
1.4 自定义异常类
我们简单的复习一下:
异常处理机制,当发现异常,系统将自动生成异常类对象,然后抛出异常交给运行时系统,系统查找是否有可以处理该异常的代码,找到匹配的 catch ,将异常交给它处理即可,如果找不到处理的代码,那么程序将被迫停止。
异常处理的两种方式:
- 捕获异常,采用 try-catch 语句。
- 抛出异常,采用 throws 在方法声明中抛出。
当 API 中提供的异常类不能满足你的需求时,需要自定义异常类。
还有一种情况是,在企业项目中,可以更明确异常位置和信息,我们需要自定义异常类。
自定义异常类,其实很简单,只需满足以下两个要求即可:
- 声明一个类需要继承 Exception 或是它的子类。
- 提供至少 2 个构造方法,一个无参构造器,一个带参构造器,参数需要包含传递的异常信息。
语法结构:
[public] class 类名 extends Exception 或是 Exception 子类
// 无参构造器
public 类名()
// 不传递默认异常信息也是可以的
super("传递默认的异常信息");
public 类名(String messag[, 参数类型 参数名 ...])
// 通过父类带一个参数的构造器,传递异常信息
super(message);
// 其他数据传递操作,和之前要求的是一样的
注意:对于异常类的类名,一般我们在命名时,可以根据作用功能进行命名,后缀加上 Exception,如:「AgeException」、「PersonException」等等。
判断数组是否为空,如果为空给出异常提示信息。
class ArrayIsNullException extends Exception
// 无参构造器
public ArrayIsNullException()
super("ArrayIsNullException: 数组长度为 0");
// 带参构造器
public ArrayIsNullException(String message)
super(message);
使用自定义异常类:
public int method1(int[] arrays, int index)
if(arrays.length == 0)
throw new ArrayIsNullException();
return arrays[index];
编译后报错提示我们必须对其进行捕获或声明以便抛出。
修改后:
/**
* 自定义异常类的使用
*/
public class TestException6
public void method1(int[] arrays, int index) throws ArrayIsNullException
if (arrays.length == 0)
//throw new ArrayIsNullException();
throw new ArrayIsNullException("数组为空,提取不到下标 " + index + " 的数组元素。");
System.out.println(arrays[index]);
public static void main(String[] args)
TestException6 te = new TestException6();
try
te.method1(new int[] , 2);
catch (ArrayIsNullException e)
System.out.println(e.getMessage());
// 自定义异常类
class ArrayIsNullException extends Exception
/**
* 无参构造器,传递默认异常信息
*/
public ArrayIsNullException()
super("ArrayIsNullException: 数组长度为 0");
/**
* 带异常信息的构造器
* @param message 异常信息
*/
public ArrayIsNullException(String message)
super(message);
本实验主要学习自定义异常类,并结合 try-catch 语句和 throws 抛出异常处理。
创建异常类,只需满足以下两个要求:
- 声明一个类需要继承 Exception 或是它的子类。
- 提供至少 2 个构造方法,一个无参构造器,一个带参构造器,参数需要包含传递的异常信息。
1.5 综合案例:
姓名要求输入不少于 1 个字符且不超过 20 个字符,否则应该抛出异常;年龄只能输入为 18 ~ 35 的 int
类型数字,否则应该抛出异常;性别只能输入 1 或 2 进行选择,否则应该抛出异常,抛出异常后应提示“请重新输入”,并且可以重新输入当前信息。
import java.util.Scanner;
public class Registration extends Exception
public Registration()
super();
public Registration(String message)
super(message);
public static Scanner input = new Scanner(System.in);
public static void main(String[] args)
System.out.println("请输入您的姓名(不小于 1 个字符且不超过 20 个字符):");
String name = new String();
do
try
name = inputName();
catch (Registration e)
System.out.println(e.getMessage());
while ((name.length()<1)||(name.length()>20));
System.out.println("请输入您的年龄(18~35):");
int age = 0;
do
try
age = inputAge();
catch (Registration e)
System.out.println(e.getMessage());
while (age<18||age>35);
System.out.println("请选择您的性别:1. 男 2. 女");
String gender = new String();
do
try
gender = setGender();
catch (Registration e)
System.out.println(e.getMessage());
while (!gender.equals("男")&&!gender.equals("女"));
System.out.println("您的报名信息为: 姓名:" + name + ";年龄:" + age + ";性别:" + gender);
/**
* 输入姓名的方法
*/
public static String inputName() throws Registration
String name=null;
name=input.next();
if(name.length()>=1&&name.length()<=20)
return name;
else
throw new Registration("你输入的姓名长度不符合要求,请重新输入:");
/**
* 输入年龄的方法
*/
public static int inputAge() throws Registration
// 补充代码
int age=input.nextInt();
if(age>=18&&age<=35)
return age;
else
throw new Registration("年龄设置为"+age+"不符合要求,请重新输入:");
/**
* 选择性别的方法
*/
public static String setGender() throws Registration
// 补充代码
String gender=input.next();
if(gender.equals("1"))
return "男";
else if(gender.equals("2"))
return "女";
else
throw new Registration("请输入1或2选择你的性别,请重新输入:");
// 内部异常类
// 补充代码
java异常处理机制(代码片段)
1.异常是指在程序的运行过程中所发生的不正常的情况或者发生错误,导致中断正在运行的程序。2.异常处理语句:try-catch,如果try代码块中捕获到异常,则到catch代码块中处理,否则跳过忽略catch代码块。(良好的编程习惯,在异... 查看详情
java异常处理机制(代码片段)
目录1.1Java异常的概念与分类1.1.1引入异常(数组越界)1.1.2 Throwable1.2Java异常捕获处理1.3异常处理finally语句使用1.3.1引入finally关键字1.3.2 采用finally释放Scanner资源1.3Java异常抛出处理1.3.1主动抛出异常1.4自定义异常类1.5综... 查看详情
java异常处理机制(代码片段)
目录1.1Java异常的概念与分类1.1.1引入异常(数组越界)1.1.2 Throwable1.2Java异常捕获处理1.3异常处理finally语句使用1.3.1引入finally关键字1.3.2 采用finally释放Scanner资源1.3Java异常抛出处理1.3.1主动抛出异常1.4自定义异常类1.5综... 查看详情
java之uncaughtexceptionhandler异常处理机制(代码片段)
JAVA之UNCAUGHTEXCEPTIONHANDLER异常处理机制1.JAVA1.5版本出现的 UNCAUGHTEXCEPTIONHANDLER当线程由于未捕获异常突然终止时调用的处理程序的接口。当一个线程由于未捕获异常即将终止时,Java虚拟机将使用thread.getuncaughtexceptionhandler()查询... 查看详情
java之uncaughtexceptionhandler异常处理机制(代码片段)
JAVA之UNCAUGHTEXCEPTIONHANDLER异常处理机制1.JAVA1.5版本出现的 UNCAUGHTEXCEPTIONHANDLER当线程由于未捕获异常突然终止时调用的处理程序的接口。当一个线程由于未捕获异常即将终止时,Java虚拟机将使用thread.getuncaughtexceptionhandler()查询... 查看详情
异常处理机制详解(代码片段)
#前言本文主要是对Java异常处理机制的阐述,了解Java的异常机制的设计和分类,及Java异常有哪些坑,如何在自定义异常类时避免采坑。#异常机制分类 异常情况是指阻止当前方法或作用域继续继续执行的情况。在Java中异常也... 查看详情
异常处理机制(代码片段)
1.异常处理1.1概念:异常就是程序在运行中出现不正常的情况并终止了程序的运行。JAVA中通过异常处理机制解决异常问题,从而保持程序继续运行;因此JAVA是一门比较稳定的语言。异常处理机制的关键字:try...catch...finally/try...c... 查看详情
java异常处理机制(代码片段)
...f0c;它阻止了程序按照程序员的预期正常执行,这就是异常,那么异常发生之后怎么办,Java提供了更加优秀的解决办法-异常处理机制。异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻... 查看详情
教妹学java:异常处理机制(代码片段)
“二哥,今天就要学习异常了吗?”三妹问。“是的。只有正确地处理好异常,才能保证程序的可靠性,所以异常的学习还是很有必要的。”我说。“那到底什么是异常呢?”三妹问。“异常是指中断程序正常执行的一个不确定... 查看详情
java异常处理机制详解(代码片段)
java异常处理机制详解程序很难做到完美,不免有各种各样的异常。比如程序本身有bug,比如程序打印时打印机没有纸了,比如内存不足。为了解决这些异常,我们需要知道异常发生的原因。对于一些常见的异常,我们还可以提... 查看详情
java中的异常处理机制(代码片段)
文章目录异常处理机制编译时异常处理机制异常处理方式一异常处理方式二异常处理方式三运行时异常处理机制异常处理机制异常的默认处理流程如下:默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException... 查看详情
java异常处理(代码片段)
java异常简介程序运行过程中出现不可以预料的错误和bug,导致程序中止或产生了错误的结果,这个现象就叫异常一、为什么要有异常处理机制?Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证... 查看详情
kotlin协程硬核解读(5.java异常本质&协程异常传播取消和异常处理机制)(代码片段)
...客】,未经博主允许不得以任何形式转载文章目录1.异常的本质1.1操作系统、程序、JVM、进程、线程1.2异常方法调用栈1.3java异常处理机制1.4小结2.Android异常处理机制3.协程异常3.1挂起函数的异常3.2throw&resumeWithException(e)3.3协... 查看详情
异常处理(代码片段)
packagecn.kecheng;importjava.util.Scanner;/**异常:异常是指在程序的运行过程中所发生的不正常的情况,它会中断正在运行的程序异常处理机制:java中通过异常处理机制为程序提供异常处理的能力,保持程序继续运行而不中断!异常处理:... 查看详情
java异常处理机制(代码片段)
...f0c;它阻止了程序按照程序员的预期正常执行,这就是异常,那么异常发生之后怎么办,Java提供了更加优秀的解决办法-异常处理机制。异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻... 查看详情
java异常处理机制(代码片段)
...f0c;它阻止了程序按照程序员的预期正常执行,这就是异常,那么异常发生之后怎么办,Java提供了更加优秀的解决办法-异常处理机制。异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻... 查看详情
springmvc--springmvc异常处理机制(代码片段)
1.SpringMVC异常处理机制1.1异常处理的思路1.2异常处理两种方式使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器1.3简单异常处理器SimpleMappingExceptionResolvSpr... 查看详情
java中异常处理机制(代码片段)
文章目录一认识常见异常1除0异常(算术异常)2数组越界异常3空指针异常二异常的体系三异常的用法(try-catch语句)1概述与代码理解2注意事项3finally语句4异常的传递5throw与throws关键字四自定义异常注意事项结语一认识常见... 查看详情