一、什么是异常

从字面上讲,就是不正常的现实就是异常。

程序中的异常也是要在程序运行中才会偶尔发生。如果程序还没有运行,编译就报错,这种不叫异常,这种叫编译错误,通常是语法上的错误

二、java中异常

Java 提供了两类主要的异常:runtime exception 和checked exception。所有的checked exception 是从java.lang.Exception 类衍生出来的,而
runtime exception 则是从java.lang.RuntimeException 或java.lang.Error类衍生出来的。它们的不同之处表现在两方面:机制上和逻辑上

所有异常必须处理!在程序里可以抛异常,但是决不能把异常抛给最终用户。
BUG 在程序员手里还不是BUG,但是一旦交付,那么就是BUG

2.1、机制上

runtime exceptions:

  • 在定义方法时不需要声明会抛出runtime exception
  • 在调用这个方法时不需要捕获这个runtime exception
  • runtime exception 是从java.lang.RuntimeException 或
  • java.lang.Error 类衍生出来的。

checked exceptions:

  • 定义方法时必须声明所有可能会抛出的checked exception
  • 在调用这个方法时,必须捕获它的checked exception,不然就得
  • 把它的exception 传递下去
  • checked exception 是从java.lang.Exception 类衍生出来的

2.2、逻辑上

从逻辑的角度来说,checked exceptions 和runtime exception 是有不同的使用目的的。

checked exception 用来指示一种调用方能够直接处理的异常情况。checked exception 迫使你捕获它并处理这种异常情况。

而runtime exception 则用来指示一种调用方本身无法处理或恢复的程序错误。

三、程序中看异常

3.1、例一

package com.pb.demo6;

import java.util.Scanner;

/*
* 求2个整数的商
* 当异常发生时,程序如何处理
*/
public class Test1 { 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 result=num1/num2;
System.out.println(num1+"与"+num2+"的商: "+result);
  System.out.println("谢谢使用!"); } }

当输入除数不是0时,正常运行,但当输入的除数为0时,或者字符串时,就会报出异常:

请输入被除数:
2
请输入除数:
0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.pb.demo6.Test1.main(Test1.java:18)
请输入被除数:
ffd
Exception in thread "main" java.util.InputMismatchException

同时也发现有异常发生时,最后的输出语句并没有执行

四、常见异常

java.lang.ArithmeticExecption
算术异常类。当出现异常的运算条件时,抛出此异常。比如程序中出现了“除以零”这样的运算,就会出这样的异常。对这种异常,大家就要好好检查一下自己程序中,涉及到数学运算的地方,公式是不是有不妥了

java.lang.NullPointerException
空指针异常类。简单地说就是调用了未经初始化的对象或者是不存在的对象。当应用程序试图在需要对象的地方使用null 时,抛出该异常这种情况包括:

  • 调用null 对象的实例方法
  • 访问或修改null 对象的字段
  • 将null 作为一个数组,获得其长度
  • 将null 作为一个数组,访问或修改其时间片
  • 将null 作为Throwable 值抛出

应用程序应该抛出该类的实例,指示其他对null 对象的非法使用

java.lang.ClassNotFoundException
找不到类异常。当应用程序试图使用以下方法通过字符串名加载类时,抛出该异常:

  • Class 类中的forName 方法
  • ClassLoader 类中的findSystemClass 方法
  • ClassLoader 类中的loadClass 方法

java.lang.ArrayIndexOutOfBoundsException
数组下标越界异常。用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引
现在程序中大多都有对数组的操作,因此在调用数组的时候一定要认真检查,看自己调用的下标是不是超出了数组的范围,一般来说,显示(即直接用常数当下标)调用不太容易出这样的错,但隐式(即用变量表示下标)调用就经常出错了,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时候,最好先查看一下数组的length,以免出现这个异常

java.lang.IllegalArgumentException
方法的参数错误异常。抛出的异常表明向方法传递了一个不合法或不正确的参数
类库中的方法在一些情况下都会引发这样的错误,比如音量调节方法中的音量参数,如果写成负数就会出现这个异常,再比如g.setColor(int red,intgreen,int blue)这个方法中的三个值,如果有超过255 的也会出现这个异常因此一旦发现这个异常,我们要做的,就是赶紧去检查一下方法调用中的参数传递是不是出现了错误

java.lang.IllegalAccessException
没有访问权限异常。当应用程序试图反射性地创建一个实例(而不是数组)、设置或获取一个字段,或者调用一个方法,但当前正在执行的方法无法访问指定类、字段、方法或构造方法的定义时,抛出该异常对程序中用了package 的情况下要注意这个异常

java.lang.IncompatibleClassChangeError
不兼容的类变化错误。当正在执行的方法所依赖的类定义,发生了不兼容的改变时,抛出该错误一般在修改了应用中的某些类的声明定义,而没有对整个应用重新编译,而直接运行的情况下,容易引发该错误

java.lang.InstantiationError
实例化错误。当应用程序试图使用Java 的new 结构,来实例化一个抽象类或一个接口时,抛出该异常通常由编译器捕获此错误,如果类定义中存在不兼容的更改,则此错误
将只可能发生在运行时

java.lang.LinkageError
链接错误。该错误及其所有子类指示一个类在一定程度上依赖于另一个类;但是,在编译前一个类之后,后一个类发生了不相容的改变

java.lang.StackOverflowError
堆栈溢出错误。当一个应用递归调用的层次太深,而导致堆栈溢出时,抛出该错误

java.lang.NumberFormatException
数字格式异常。当试图将一个String 转换为指定的数字类型,而该字符串却不满足数字类型要求的格式时,抛出该异常

java.lang.RuntimeException
运行时异常。RuntimeException 是那些可能在Java 虚拟机正常运行期间抛出的异常的超类可能在执行方法期间抛出但未被捕获的RuntimeException 的任何子类,都无需在throws 子句中进行声明

java.io.IOException
输入输出异常。当发生某种I/O 异常时,抛出此异常。此类是失败或中断的I/O 操作生成的异常的通用类

java.io.FileNotFoundException
文件未找到异常。当试图打开指定路径名表示的文件失败时,抛出此异常
在不存在具有指定路径名的文件时,此异常将由FileInputStream、FileOutputStream 和RandomAccessFile 构造方法抛出。如果该文件存在,但是由于某些原因不可访问,比如试图打开一个只读文件进行写入,则此时这些构造方法仍然会抛出该异常

java.io.EOFException
文件已结束异常。当输入过程中意外到达文件或流的末尾时,抛出此异常
此异常主要被数据输入流用来表明到达流的末尾。注意,其他许多输入操作返回一个特殊值表示到达流的末尾,而不是抛出异常

java.lang.InterruptedException
被中止异常。当线程在活动之前,或活动期间处于正在等待、休眠或占用状态,且该线程被中断时,抛出该异常有时候,一种方法可能希望,测试当前线程是否已被中断,如果已被中断,则立即抛出此异常

五、异常处理

5.1、语法格式:

try{
// 有可能出现异常的语句
}catch(异常类 异常对象){
// 编写异常的处理语句
}[ catch(异常类 异常对象){
// 编写异常的处理语句
} catch(异常类 异常对象){
// 编写异常的处理语句
} …. ]
[finally{
一定会运行到的程序代码 ;
}

主要搭配:try-catch、try-catch-finally、try-finally三种形式

5.2、多个异常

如果同时有多个catch块,Exception 必须放在最后一个catch块中

package com.pb.demo6;

import java.util.InputMismatchException;
import java.util.Scanner; import javax.naming.AuthenticationException; /*
* 求2个整数的商
* 当异常发生时,程序如何处理
*/
public class Test1 { public static void main(String[] args) {
//从键盘获得输入
try{
Scanner input=new Scanner(System.in);
System.out.println("请输入被除数:");
int num1=input.nextInt();
System.out.println("请输入除数:");
int num2=input.nextInt();
int result=num1/num2;
System.out.println(num1+"与"+num2+"的商: "+result);
}catch(InputMismatchException e){
System.out.println("输入的不是数字");
e.printStackTrace(); }catch(ArithmeticException e){
System.out.println("除数不能为0");
e.printStackTrace();
}catch(Exception e){
System.out.println("其它错误!");
e.printStackTrace();
}finally{
System.out.println("谢谢使用!");
} } }
请输入被除数:
2
请输入除数:
0
除数不能为0
java.lang.ArithmeticException: / by zero
at com.pb.demo6.Test1.main(Test1.java:22)
谢谢使用!

在finally中的语句,不管出不出异常都会被执行.

但如果在catch块中:执行System.exit(0);或者System.exit(-1);程序将直接结束,finally中的语句将不会执行

5.3、Java的异常处理机制

在整个java的异常处理中,实际上也是按照面向对象的方式进行处理,处理的步骤如下:
  • 一旦产生异常,则首先会产生一个异常类的实例化对象;
  • 在try语句中对此异常对象进行捕捉;
  • 产生的异常对象与catch语句中的各个异常类型进行匹配,如果匹配成功,则执行catch语句中的代码

六、抛出异常

6.1、throws关键字

在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用处进行处理 。
throws使用格式
public 返回值类型 方法名称(参数列表…) throws 异常类{}
package com.pb.demo6;

import java.util.InputMismatchException;
import java.util.Scanner; import javax.naming.AuthenticationException; /*
* 求2个整数的商
* 当异常发生时,程序如何处理
*/
public class Test2 { public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } //除法运算
public static void divide () throws Exception{
//从键盘获得输入
Scanner input=new Scanner(System.in);
System.out.println("请输入被除数:");
int num1=input.nextInt();
System.out.println("请输入除数:");
int num2=input.nextInt();
int result=num1/num2;
System.out.println(num1+"与"+num2+"的商: "+result);
}
}

6.2、throw关键字

与throws不同的是,可以直接使用throw抛出一个异常。抛出的时候直接抛出异常类的实例化对象即可
package com.pb.demo6;
/*
* 人类
*/
public class Person {
private String name;
private String sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) throws Exception {
if(sex.equals("男") || sex.equals("女")){
this.sex = sex;
}else{
throw new Exception("性别只能是男或者女");
} }
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=0 && age<=150){
this.age = age;
}else{
try {
throw new Exception("年龄只能在0-150岁之间!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void printSelf(){
System.out.println("姓名:"+this.name+" 性别:"+this.sex+" 年龄:"+this.age);
} }
package com.pb.demo6;

public class PersonTest {

    public static void main(String[] args) {
Person p=new Person(); try {
p.setName("张三");
p.setSex("不男不女");
p.setAge(200);
p.printSelf();
} catch (Exception e) {
e.getMessage();
e.printStackTrace();
} } }

七、自定义异常

在Java中已经提供了大量的异常类,但是这些异常类有些时候也很难满足开发者的要求,所以此时用户可以根据自己的需要定义自己的异常类,定义异常类,只需要继承Exception类即可。
当然可以继承其它的如:Exception,Throwable,RuntimeException及其子类,其中继承Exception,Throwable,效果,如果不要求调用者一定要处理抛出的异常可以继承RuntimeException及其子类
调用时只需要throw new 自定义异常名(信息)
package com.pb.demo6;

public class MyException extends Exception {

    public MyException() {
super();
// TODO Auto-generated constructor stub
} public MyException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
} public MyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
} public MyException(String message) {
super(message);
// TODO Auto-generated constructor stub
} public MyException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
} }
package com.pb.demo6;
/*
* 人类
*/
public class Person {
private String name;
private String sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) throws Exception {
if(sex.equals("男") || sex.equals("女")){
this.sex = sex;
}else{
throw new MyException("性别只能是男或者女");
} }
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=0 && age<=150){
this.age = age;
}else{
try {
throw new MyException("年龄只能在0-150岁之间!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void printSelf(){
System.out.println("姓名:"+this.name+" 性别:"+this.sex+" 年龄:"+this.age);
} }
package com.pb.demo6;

public class PersonTest {

    public static void main(String[] args) {
Person p=new Person(); try {
p.setName("张三");
p.setSex("不男不女");
p.setAge(200);
p.printSelf();
} catch (Exception e) {
e.getMessage();
e.printStackTrace();
} } }

com.pb.demo6.MyException: 性别只能是男或者女

这时获得的异常就是我们自定义的异常

Java从零开始学十九(异常)的更多相关文章

  1. Java从零开始学十四(包和访问控制)

    一.java中的包 Java文件的组织形式Windows中的文件功能类似 在开发比较大的项目时,不可能只涉及到一个java文件,可能要创建几十,甚至几百个java文件,这个时候,我们就可以使用包,把相 ...

  2. Java从零开始学十八(抽象类和接口)

    一.什么是抽象类和接口 抽象类.接口与类是一个层次的概念,是java中极其重要的概念. 抽象类是从多个类中抽象出来的公共模板,提供子类均具有的功能. 接口是从多个类中抽象出来的规范,体现的是规范和实现 ...

  3. Java从零开始学十六(多态)

    一.什么是多态 多态性是指允许不同类的对象对同一消息作出响应.多态性包括参数化多态性和包含多态性.多态性语言具有灵活.抽象.行为共享.代码共享的优势,很好的解决了应用程序函数同名问题.多态有两种表现形 ...

  4. Java从零开始学十五(继承)

    一.继承作用 继承使用复用以前的代码非常容易,能够大大的缩短开发周期,降低开发成本,同时增加程序的易维护性 继承使重一个类A能够直接使用另外一个类B的属性和方法的一种途径 类A可以有自己的属性和方法 ...

  5. Java从零开始学十(Arrays类对数组的常用方法)

    一.Arrays类常用方法 二.简单例子 package com.pb.demo1; import java.util.Arrays; /* * Arrays工具类的中的几个常用方法 * 1.copy ...

  6. Java从零开始学十二(构造方法)

    一.构造方法 构造方法的主要目的是为类中的属性初始化 二.构造方法的定义格式 class 类名称{ 访问权限 类名称(类型1 参数1,类型2 参数2,…){ 程序语句 ; …    // 构造方法没有 ...

  7. Java IO(十九)PrintStream 和 PrintWriter

    Java IO(十九)PrintStream 和 PrintWriter 一.介绍 (一).PrintStream PrintStream 是打印输出流,它继承于FilterOutputStream. ...

  8. Java进阶(三十九)Java集合类的排序,查找,替换操作

    Java进阶(三十九)Java集合类的排序,查找,替换操作 前言 在Java方向校招过程中,经常会遇到将输入转换为数组的情况,而我们通常使用ArrayList来表示动态数组.获取到ArrayList对 ...

  9. “全栈2019”Java多线程第二十九章:可重入锁与不可重入锁详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. poj 3041 Asteroids 最小点覆盖/最大匹配

    Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16242 Accepted: 8833 Descriptio ...

  2. 读书笔记_Effective_C++_条款三十四:区分接口继承和实现继承

    这个条款书上内容说的篇幅比较多,但其实思想并不复杂.只要能理解三句话即可,第一句话是:纯虚函数只继承接口:第二句话是:虚函数既继承接口,也提供了一份默认实现:第三句话是:普通函数既继承接口,也强制继承 ...

  3. JavaScript Promises

    上篇文章介绍了JavaScript异步机制,请看这里. JavaScript异步机制带来的问题 JavaScript异步机制的主要目的是处理非阻塞,在交互的过程中,会需要一些IO操作(比如Ajax请求 ...

  4. html div 宽度随着浏览器自动适应

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. window server 2012 更改密钥 更改系统序列号

    由于在window server 2012当中,好像更改密钥的方法,给隐藏了,没办法激活,这里记录一下在网上查找到的一个命令行,如何在window server 2012 更改密钥 更改系统序列号 在 ...

  6. 你得学会并且学得会的Socket编程基础知识(续)——Silverlight客户端

    本文将在这个案例的基础上,加入一个特殊场景,利用Silverlight来实现客户端.有的朋友可能会说,其实是一样的吧.请不要急于下结论,有用过Silverlight的朋友都有这种体会,很多在标准.NE ...

  7. MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转)

    本文转自https://m.imooc.com/article/details?article_id=17290 感谢作者 上篇记录了我对MySQL 事务 隔离级别read uncommitted的理 ...

  8. myeclipse 修改freemarker ftl 不重启tomcat

    最 近的项目是SSH,View层采用Freemarker,但是遇到了一个很大问题,每次修改完ftl文件,都要重新启动tomcat才可以看到所修改的内 容,不但麻烦,而且浪费时间,特别怀念jsp,后来在 ...

  9. [PHP] ubuntu16.04下 Phpstorm发布项目到apache

    reference to : http://blog.csdn.net/qq_23937195/article/details/72953308 在网上找的不靠谱,倒腾了大半天的,终于找到正确姿势QA ...

  10. 【BZOJ】【2741】【FOTILE模拟赛】L

    可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成 ...