Java入门系列-20-异常
为什么要进行异常处理
下面这段代码能否正常执行
public class DemoCalc {
public static void main(String[] args) {
int a=0;
int b=0;
int c=a/b;
System.out.println("运算结果为:"+c);
}
}
结果是我们在控制台中看到一段错误提示,那是因为除数不能为0。异常就是在程序运行过程中发生的不正常事件,会中断运行的程序。
Java 使用了异常处理机制为程序提供了错误处理的能力,在程序中预先设置好对付异常的处理办法,待程序发生异常时对异常进行处理,处理完毕后,程序便可以继续运行。
下面来看一下Java中是如何进行异常处理的
如何进行异常处理
Java 的异常处理是通过5个关键字实现的:try、catch、finally、throw、throws
| 关键字 | 作用 |
|---|---|
| try | 执行可能产生异常的代码 |
| catch | 捕获异常 |
| finally | 无论是否发生异常,代码总能执行 |
| throws | 声明方法要抛出的异常 |
| throw | 手动抛出异常 |
常见异常及异常分类
Throwable 是Java 中所有错误和异常的父类
Error类:Throwable的子类,仅靠程序本身无法恢复的严重的错误。
Exception类:Throwable的子类,由Java应用程序抛出和处理的非严重错误
RuntimeException类:Exception的子类,运行时异常,不要求程序必须做出处理。
Checked异常:Exception的子类,程序必须处理该类异常。
常见异常类型
| 异常类型 | 说明 |
|---|---|
| Exception | 异常层次结构的父类 |
| ArithmeticException | 算数错误情形,如以零作除数 |
| ArrayIndexOutOfBoundsException | 数组下标越界 |
| NullPointerException | 尝试访问null对象成员 |
| ClassNotFoundException | 不能加载所需的类 |
| IllegalArgumentException | 方法接收到非法参数 |
| ClassCastException | 对象强制类型转换出错 |
| NumberFormatException | 数字格式转换异常,如把"abc"转换成数字 |
try-catch
语法:
public void method(){
try{
//代码段1
//可能产生异常的代码段
//代码段2
}catch(异常类型 ex){
//对异常进行处理的代码段
}
//代码段
}
try-catch块捕获异常有三种情况:
1、try块中没有任何异常,try中正常,catch不会执行,正常执行try-catch后的代码。
2、try块中可能发生异常的代码段发生异常,代码段2不会执行,而是执行catch中异常处理的代码,正常执行try-catch后的代码。
catch中异常类型的printStackTrace() 方法能进行堆栈跟踪显示出程序运行到当前类的执行流程,异常堆栈信息中包含了异常的类型及异常出现的位置。
3、异常类型不匹配,程序将中断。比如try产生的异常为ArithmeticException,catch却用了 ClassCastException。
在控制台中接收数字做除法运算
import java.util.Scanner;
public class DemoInput {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
try{
System.out.println("请输入被除数(整数):");
int a=input.nextInt();
System.out.println("请输入除数(整数):");
int b=input.nextInt();
int c=a/b;
System.out.println("结果:"+c);
}catch(Exception ex) {
ex.printStackTrace();
}
System.out.println("程序结束");
}
}
try-catch-finally
语法:
public void method(){
try{
//可能会发生异常的代码
}catch(异常类型 ex){
//异常处理
}finally{
//无论如何都要执行的代码
}
}
finally块:是否发生异常都执行
finllay块不执行的唯一情况:之前的代码中执行了 System.exit(1); 退出虚拟机
try-catch-finally的使用
import java.io.FileNotFoundException;
import java.util.Scanner;
public class DemoInput {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
try{
System.out.println("请输入被除数(整数):");
int a=input.nextInt();
System.out.println("请输入除数(整数):");
int b=input.nextInt();
int c=a/b;
System.out.println("结果:"+c);
}catch(Exception ex) {
ex.printStackTrace();
}finally {
System.out.println("感谢您的使用");
}
System.out.println("程序结束");
}
}
如果在try块或catch块中有return语句,finally是否还会执行?运行下面代码断点调试观察结果。
public class TestReturn {
public static void main(String[] args) {
try {
int a=1+1;
System.out.println("try执行");
return;
} catch (Exception e) {
System.out.println("catch执行");
}finally {
System.out.println("finally执行");
}
}
}
try块或catch块中可以有return语句,如果有return语句会先执行finally最后再执行return。
多重catch
try块中可能会发生多种异常,如果要不同的异常进行不同的处理,需要使用多重catch进行处理。
语法:
public void method(){
try{
//可能发生异常的代码段
}catch(异常类型1 e){
//对异常类型1进行的处理的代码段
}catch(异常类型2 e){
//对异常类型2进行的处理的代码段
}catch(异常类型n e){
//对异常类型n进行的处理的代码段
}
}
当try块中发生异常后,会逐个与catch中的异常类型进行匹配,匹配成功后,进入对应的catch进行异常处理,处理完成后不再进入其他catch,程序继续执行。
排列catch语句的顺序是:先子类后父类
发生异常时按顺序逐个匹配
只执行第一个与异常类型匹配的catch语句
将之前的代码 DemoInput.java 改造成多重catch
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class DemoInput {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
try{
System.out.println("请输入被除数(整数):");
int a=input.nextInt();
System.out.println("请输入除数(整数):");
int b=input.nextInt();
int c=a/b;
System.out.println("结果:"+c);
}catch(InputMismatchException e) {
System.out.println("输入的数有误!");
}catch(ArithmeticException e) {
System.out.println("除数不能为0");
}catch(Exception ex) {
System.out.println("发生未知异常");
}finally {
System.out.println("感谢您的使用");
}
System.out.println("程序结束");
}
}
声明异常 throws
如果一个方法体内抛出了异常如何通知调用者,可以在方法上声明异常。
public class TestThrows {
//声明异常,多个异常可以用逗号隔开
public void test()throws Exception,ClassNotFoundException{
//可能会发生异常的代码
}
}
处理方式一:调用者处理异常
public static void main(String[] args) {
TestThrows t=new TestThrows();
try {
t.test();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
处理方式二:调用者继续声明异常
public static void main(String[] args) throws ClassNotFoundException, Exception {
TestThrows t=new TestThrows();
t.test();
}
main方法继续声明异常,调用者就变成虚拟机了,发生异常则按默认方式处理,打印出来。
抛出异常 throw
除了系统自动抛出的异常外,有些问题需要程序员自行抛出异常
public class TestThrow {
public void inputAge(int age) throws Exception {
if (age<1) {
throw new Exception("还有这种年龄?");
}
}
public static void main(String[] args) {
TestThrow t=new TestThrow();
try {
t.inputAge(-1);
} catch (Exception e) {
System.out.println("年龄有误:"+e.getMessage());
}
}
}
自行抛出异常后,还需要在方法上声明异常
Java入门系列-20-异常的更多相关文章
- Java入门系列-19-泛型集合
集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...
- java io系列20之 PipedReader和PipedWriter
本章,我们学习PipedReader和PipedWriter.它们和“PipedInputStream和PipedOutputStream”一样,都可以用于管道通信. PipedWriter 是字符管 ...
- Java入门系列-26-JDBC
认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...
- 夯实Java基础系列20:从IDE的实现原理聊起,谈谈那些年我们用过的Java命令
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- Java入门系列之集合ArrayList源码分析(七)
前言 上一节我们通过排队类实现了类似ArrayList基本功能,当然还有很多欠缺考虑,只是为了我们学习集合而准备来着,本节我们来看看ArrayList源码中对于常用操作方法是如何进行的,请往下看. A ...
- Java入门系列 泛型
前言 <Java编程思想>第四版足足用了75页来讲泛型——厚厚的一沓内容,很容易让人头大——但其实根本不用这么多,只需要一句话:我是一个泛型队列,狗可以站进来,猫也可以站进来,但最好不要既 ...
- Java入门系列:实例讲解ArrayList用法
本文通过实例讲解Java中如何使用ArrayList类. Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征.可以随时从链表中添 ...
- Java入门系列(九)Java API
String,StringBuilder,StringBuffer三者的区别 1.首先说运行速度,或者说是执行速度 在这方面运行速度快慢为:StringBuilder > StringBuffe ...
- Java入门系列(七)Java 集合框架(JCF, Java Collections Framework)
Java 集合概述 List.Set.Map可以看做集合的三大类 java集合就像一个容器,可以将多个对象的引用丢进该容器中. Collection和Map是java集合的根接口. List List ...
- Java入门系列(五)JVM内存模型
概述 根据<Java 虚拟机规范>中的说法,Java 虚拟机的内存结构可以分为公有和私有两部分. 公有指的是所有线程都共享的部分,指的是 Java 堆.方法区.常量池. 私有指的是每个线程 ...
随机推荐
- Transaction And Lock--解决死锁/锁的几种有效方式
修改资源访问顺序,使多个事务对资源的访问方式一致优化查询SELECT,使得S锁能尽早释放均可能将更新和删除语句放到事务末端(使得X锁占用时间最小)避免事务执行期间暂停或等待外部输入将较大事务拆分成多个 ...
- C# TinyIOC简单用法
先添加一个接口 namespace IContract { public interface IBase { void ShowMessage(); } } 再添加两个实现类 namespace Co ...
- Linux/Unix监控工具vmstat命令
注:内容来之网络 vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Li ...
- Bitnami WordPress如何让默认URL指向WordPress目录?
Bitnami WordPress下载地址:https://bitnami.com/stack/wordpress/installer ,根据自己操作系统选择对应版本,我是windows server ...
- 使用ActiveMQ实现简易聊天功能
一 什么是消息队列 我们可以把消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用.消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系统性能和削峰. ...
- maven(私库)上传jar包
在实际开发过程中,我们经常会遇到需要引用的jar依赖,在我们公司的maven仓库不存在,这个时候我们就需要把jar上传上去,在项目中添加对应依赖就OK了. 步骤1:下载jar 在http://mvnr ...
- PHP 执行系统外部命令的方法 system() exec()
PHP作为一种服务器端的脚本语言,像编写简单.或者是复杂的动态网页这样的任务,它完全能够胜任.但事情不总是如此,有时为了实现某个功能,必须借助于操作系统的外部程序(或者称之为命令),这样可以做到事半功 ...
- linux开始之旅-01 linux需要知道的这几位
首先介绍几个人,没有这几个人就没有linux. 第一个:肯·汤普逊(左)和丹尼斯·里奇(右) ------ C语言之父 ------学计算机的人都应该认识吧,计算机学院楼道里面都会有这两位. 美 ...
- CentOS加入Windows域
CentOS加入Windows域,为减少操作已经提前关掉了selinux,防火墙.并且更改了主机名 yum install nss-pam-ldapd -y 第一步:更改主机名为linux.itxd ...
- C#中简单操作Mysql数据库
以C#访问MySQL数据库,执行简单的CRUD. MySql.Data.dll是C#操作MySQL的驱动文件,是C#连接MySQL必要插件,使C#语言更简洁的操作MySQL数据库.可以用NuGet命令 ...