异常
异常
1 三种类型的异常:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
2 Java异常处理涉及到五个关键字,分别是:try、catch、finally、throw、throws。下面将骤一介绍,通过认识这五个关键字,掌握基本异常处理知识。
• try -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
• catch -- 用于捕获异常。catch用来捕获try语句块中发生的异常。
• finally -- finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
• throw -- 用于抛出异常。
• throws -- 用在方法签名中,用于声明该方法可能抛出的异常。
3 Java的异常类型
1 编译时异常:
1、除0发生算数异常(ArithmeticException)
关键技术解析:在数学中,除0的操作时不对的,在Java程序中也是这样,一个被除数为0,就要抛出异常.
2、数组下标越界异常(ArrayIndexOutOfException)
关键技术解析:ArrayIndexOutOfException异常用非法索引访问数组时抛出的异常,如果索引为负或大于等于数组大小,则该索引为非法索引。
3、数组元素类型不匹配异常(ArrayStoreExption)
关键技术解析:定义三个不同类型的元素对象,这三个元素对象相互组合,就会出现数组元素类型不匹配异常。试图将错误类型的对象储存到一个对象数组时抛出异常。
4、强制类型转换异常(ClassCastException)
关键技术解析:在进行转换时,转换的两个类型不匹配,就会发生异常。
5、索引越界异常(IndexOutOfBoundsException)
关键技术解析:索引越界异常在某排序索引(例如对字符串或数组的排序)超出范围是抛出。应用程序可以为这个类创建子类,以指示类似的异常。
6、空指针异常(NullPointerException)
关键技术解析:当应用程序试图在需要对象的地方使用null时,抛出该异常。这种情况包括:
a.调用null对象的实例方法
b.访问或修改null对象的字段
c.应用程序应该抛出该类实例,只是其他对null对象的非法使用
7、数字格式转换异常(NumberFornatException)
关键技术解析:当应用试图把一个字符串转换成一个数值类型,但这个字符串没有恰当的格式时就会抛出数字格式转换异常。
8、字符串索引越界异常(StringIndexOutException)
关键技术解析:StringIndexOutException异常用非法索引访问字符串抛出的异常。如果索引为负或大于等于字符串的大小,则该索引为非法索引。
8、操作错误(UnsupportedOperationException)
关键技术解析:java.lang.UnsupportedOperationException异常是由于Arrays.asList()返回java.util.Arrays$ArrayList,而不是ArrayList。Arrays$ArrayList和ArrayList都是继承AbstractList,add等方法在AbstractList中是默认抛出UnsupportedOperationException而且不做任何操作。
2 运行时异常
1、找不到指定类时发生的异常(ClassNotFoundException)
关键技术解析:
a.当程序加载Class类中的forName()方法时,异常抛出。同时,也有其它方法可以抛出同样的异常,如:ClassLoader类中的findSystemClass方法,loadClass方法。
b.在构造时提供并通过getException()方法访问的"加载类是引发的可选异常",现在被称为原因,它可以通过Throwable.getCause()方法以及上面提到的"遗留犯方法"来访问。
2、请求的方法不存在(NoSuchMethodException)
关键技术解析:当应用试图调用某个类的某种方法,而该类中没有该方法的定义时抛出该异常。
下面是两种常见异常
package com.example;
import java. util .Scanner ;
public class AllDemo
{
public static void main (String [] args )
{
System . out. println( "----欢迎使用命令行除法计算器----" ) ;
CMDCalculate ();
}
public static void CMDCalculate ()
{
Scanner scan = new Scanner ( System. in );
int num1 = scan .nextInt () ;
int num2 = scan .nextInt () ;
int result = devide (num1 , num2 ) ;
System . out. println( "result:" + result) ;
scan .close () ;
}
public static int devide (int num1, int num2 ){
return num1 / num2 ;
}
}
/*****************************************
----欢迎使用命令行除法计算器----
2
0
Exception in thread "main" java.lang.ArithmeticException : / by zero
at com.example.AllDemo.devide( AllDemo.java:30 )
at com.example.AllDemo.CMDCalculate( AllDemo.java:22 )
at com.example.AllDemo.main( AllDemo.java:12 )
----欢迎使用命令行除法计算器----
1
r
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor( Scanner.java:864 )
at java.util.Scanner.next( Scanner.java:1485 )
at java.util.Scanner.nextInt( Scanner.java:2117 )
at java.util.Scanner.nextInt( Scanner.java:2076 )
at com.example.AllDemo.CMDCalculate( AllDemo.java:20 )
at com.example.AllDemo.main( AllDemo.java:12 )
*****************************************/
4 异常的分层结构
5 异常处理的基本语法
在编写代码处理异常时,对于检查异常,有2种不同的处理方式:使用try...catch...finally语句块处理它。或者,在函数签名中使用throws 声明交给函数调用者caller去解决。
1 try...catch...finally
try{
//try块中放可能发生异常的代码。 //如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码(如果有的话)。 //如果发生异常,则尝试去匹配catch块。
}catch(SQLException SQLexception){
//每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。
//catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。
//在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。
//如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部caller中去匹配异常处理器。 //如果try中没有发生异常,则所有的catch块将被忽略。
}catch(Exception exception){
//...
}finally{
//finally块通常是可选的。 //无论异常是否发生,异常是否匹配被处理,finally都会执行。
//一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。
//finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。
需要注意的地方
public static void main(String[] args){
try {
foo();
}catch(ArithmeticException ae) {
System.out.println("处理异常");
}
}
public static void foo(){
int a = 5/0; //异常抛出点
System.out.println("为什么还不给我涨工资!!!"); //////////////////////不会执行
}
2 throws 函数声明
throws声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉,则javac保证你必须在方法的签名上使用throws关键字声明这些可能抛出的异常,否则编译不通过。
throws是另一种处理异常的方式,它不同于try...catch...finally,throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。
采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责
public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN
{
//foo内部可以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的子类的异常对象。
}
3 throw 异常抛出语句
throw exceptionObject
程序员也可以通过throw语句手动显式的抛出一个异常。throw语句的后面必须是一个异常对象。
throw 语句必须写在函数中,执行throw 语句的地方就是一个异常抛出点,它和由JRE自动形成的异常抛出点没有任何差别。
public void save(User user)
{
if(user == null)
throw new IllegalArgumentException("User对象为空");
//......
}
6 自定义异常
在程序中使用自定义异常类,大体可分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过
throw关键字抛出异常对象。 - 如果在当前抛出异常的方法中处理异常,可以使用
try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。 - 在出现异常方法的调用者中捕获并处理异常。
class MyException extends Exception { private int detail; MyException(int a){ detail = a; } public String toString(){ return "MyException ["+ detail + "]"; } } public class TestMyException{ static void compute(int a) throws MyException{ System.out.println("Called compute(" + a + ")"); if(a > 10){ throw new MyException(a); } System.out.println("Normal exit!"); } public static void main(String [] args){ try{ compute(1); compute(20); }catch(MyException me){ System.out.println("Caught " + me); } } }
浙公网安备 33010602011771号