目录
Java 异常概述
异常的抛出机制
异常的解决方法(处理机制)
Java异常体系结构
常见的异常
异常处理
try
catch
finally
throws
throw
运行期异常和编译期异常
自定义异常
Java 异常概述
在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行
过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式
,读取文件是否存在,网络是否始终保持通畅等等。
异常:程序在运行过程中出现的不正常情况 例如用户输入的信息不正确,或者在网络传输中忽然断网了等等 出现异常后,Jvm(虚拟机)停止运行,后续程序无法执行 注意:异常指得不是语法错误。语法错误,编译失败,不会产生字节码文件,根本不能运行
异常的抛出机制
异常的解决方法(处理机制)
第一种(默认):是遇到错误就终止程序的运行。将Java中出现的异常,按不同的类型进行分类,为
每种异常分装了一个类来进行表示当出现某种异常情况时,会抛出此类的对象,然后终止虚拟机的
运行。
第二种是程序员在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在
无法避免的,要编写相应的代码进行异常的检测、以及异常的处理,保证代码的健壮性。使用异常
处理机制,对程序运行过程中的异常进行捕获和处理
Java异常体系结构
java.lang.Throwable类是Java程序执行过程中发生的异常事件对应的类的根父类。
Throwable中的常用方法:
public void printStackTrace():打印异常的详细信息。
包含了异常的类型、异常的原因、异常出现的位置、在开发和调试阶段都得使用printStackTrace。
public String getMessage():获取发生异常的原因。
Throwable可分为两类:Error和Exception。分别对应java.lang.Errorjava.lang.Exception两个类。
Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不
编写针对性的代码进行处理。
例如:StackOverflowError(栈内存溢出)和OutOfMemoryError(堆内存溢出,简称OOM)。
Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处
理,使程序继续运行。否则一旦发生异常,程序也会终止。
常见的异常
Error:
堆溢出: OutOfMemoryError
栈溢出: StackOverflowError
public class Demo {
/*
异常:程序在运行过程中出现的不正常情况
例如用户输入的信息不正确,或者在网络传输中忽然断网了等等
出现异常后,Jvm(虚拟机)停止运行,后续程序无法执行
注意:异常指得不是语法错误。语法错误,编译失败,不会产生字节码文件,根本不能运行
Java中默认的异常处理机制:将Java中出现的异常,按不同的类型进行分类,为每种异常分装了一个类来进行表示
当出现某种异常情况时,会抛出此类的对象,然后终止虚拟机的运行
使用异常处理机制,对程序运行过程中的异常进行捕获和处理
*/
public static void main(String[] args) {
int []a=new int[2];
System.out.println(a[3]);
/*
六种常见的异常
int a = 10;
int b = 0;
if(b!=0)
System.out.println(a/b); ArithmeticException 算术异常
int[] c = new int[2];
c[3] = 0; ArrayIndexOutOfBoundsException 数组索引越界
String s = "abc";
s.charAt(4); StringIndexOutOfBoundsException 字符串索引越界
Object s = new Integer(10);
String s1 = (String)s; ClassCastException 类型转换异常
int a = Integer.parseInt("10a");// NumberFormatException 数字格式化异常
String s = null;
s.length(); NullPointerExceptio 使用null中的方法/属性 一般在java中也称为 空指针异常
*/
}
}
异常处理
Java编程语言使用异常处理机制为程序提供了错误处理的能力
Java的异常处理是通过5个关键字来实现的:try、catch、finally、throw、throws
try
检测不安全的代码块(发现异常)
try块中任何一条语句发生了异常,下面的代码将不会被执行,程序将 跳转到异常处理代码块中,
即catch块。因此,不要随意将不相关的代码放到try块中,因为随时可能会中断执行。
catch
把抓到的类型匹配的异常捕获,保证程序能继续运行下去
catch语句必须紧跟着try语句之后,称为捕获异常,也就是异常处理函数。
一个try后面可以写多个catch,分别捕获不同类型的异常,要从子类往父类的顺序写,否则有编译错误
捕获异常的有关信息:
与其它对象一样,可以访问一个异常对象的成员变量或调用它的方法。
getMessage() 获取异常信息,返回字符串
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
public class Demo1 {
/*
异常处理:
在编码时,就针对可能出现问题的代码(可能是经验问题)预习编写一些处理机制来对代码进行处理,步骤一般为以下四步
程序运行
出现异常
执行处理机制
继续运行后续的程序
try{
编写可能出现异常的代码
如果类型为算术异常,但catch捕捉的类型为数组越界异常,则不会进入到catch中
}catch(异常类型 比如数组越界异常 ){
处理机制
}
*/
public static void main(String[] args) {
int a = 10;
int b = 0;
/*
int []aa=new int[2];
int bb=aa[3];
在此之前出现错误时,则不执行后续代码
*/
try{
int c = a/b;//算术运算
}catch (ArithmeticException ai){
ai.printStackTrace();//打印异常信息到控制台,一般在开发调试阶段使用,供开发人员定位异常问题
System.out.println("算术异常");
}
System.out.println("Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
}
public class Demo2 {
public static void main(String[] args) {
try{
String s = null;
s.length();
int num = Integer.parseInt("10a");
int [] a = new int[5];
for (int i = 0; i <=a.length ; i++) {
System.out.println(a[i]);
}
}catch (ArrayIndexOutOfBoundsException ai){
ai.printStackTrace();
System.out.println("数组索引越界,越界索引:"+ai.getMessage());//拿到异常原因
}catch (NumberFormatException nex){
nex.printStackTrace();
System.out.println("数字格式化异常:"+nex.getMessage());
}catch (Exception e){ //在后面catch Exception类型, 可以捕获任意的异常类型,但是必须要放到最后面,因为下面可能有更加详细类型的捕捉,如果使用Exception类型,那么就一定会进入这个catch,运用了多态
e.printStackTrace();
System.out.println("系统忙 请稍后再试");
}
System.out.println("aaaaaaaaaaaaaaaaaa");
}
}
finally
finally该内容总是会执行的,只能有一个finally语句
finally{
必须执行的内容 }
public class Demo3 {
/*
异常处理:
在编码时,就针对可能出现问题的代码(可能是经验问题)预习编写一些处理机制来对代码进行处理,步骤一般为以下四步
程序运行
出现异常
执行处理机制
继续运行后续的程序
try{
编写可能出现异常的代码
如果类型为算术异常,但catch捕捉的类型为数组越界异常,则不会进入到catch中
}catch(异常类型 数组越界异常 ){
处理机制
}finally{
finally代码块中的内容总能执行, 一定会执行
}
*/
public static void main(String[] args) throws IOException {
//应用场景1
try{
int num = Integer.parseInt("10a");
}catch (ArrayIndexOutOfBoundsException nex){
nex.printStackTrace();
}finally { //异常没有被捕获到,后面的代码无法执行,但是finally中的代码是可以执行的
System.out.println("qqqqqqqqqqqqqqqqqqqqqqqq");
}
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
//应用场景2
FileInputStream in = null;
try {
in = new FileInputStream("D:/demo10086.txt");//文件一旦找不到,就会出现异常
while (in.read()!=-1){
}
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("文件找不到异常");
}finally { //确保在出现异常的情况下 依然最终把流对象关闭掉
if(in!=null){
in.close();
}
}
System.out.println("aaaaaaaaaaaaaaaaaa");
//应用场景3
test(10,5);
System.out.println("aaaaaaaaaaaaaaaaaa");
}
public static int test(int a,int b){
try {
return a/b;
}catch (ArithmeticException ae){
ae.printStackTrace();
System.out.println("算术异常");
return -1;
}finally { // 无论是try中还是catch进行return,也必须在return之前 先执行finally代码块
//关闭流操作
System.out.println("关闭流");
}
}
}
throws
定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而交给方法调用处进
行处理。
例如:
public void test throws 异常1,异常2,异常3{ 代码 }
任何方法都可以使用throws关键字声明异常类型,包括抽象方法。
调用使用了throws的方法时必须处理声明的异常,要么使用try-catch,要么继续使用throws声
明。
如果抛出的是运行期异常,则不会有任何提示,需要查看所调用的方法结构.
public class Demo4 {
public static void main(String[] args) {
try {
//最顶层的main方法中就不能再抛出了,必须对异常进行处理
methodA();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.out.println("编码异常");
}
System.out.println("main");
}
public static void methodA() throws UnsupportedEncodingException {
methodB();
System.out.println("methodA");
}
/*
用methodB方法模拟一个底层方法
throws 异常类型 声明表示此方法中可能会出现给定的异常, 并且该方法不处理异常
谁调用谁处理
异常(Exception)分为俩类:
检查期异常:在编译期间就会主动提示程序员要进行处理的异常
运行期异常:在编译期间不会主动提示程序员要进行处理的异常
区别在于该异常类有没有继承RuntimeException
*/
public static void methodB() throws UnsupportedEncodingException {
String s = "abc";
s.getBytes("gbk-1"); //根据一个编码表进行转换;(正确为gbk) throws UnsupportedEncodingException 表示此方法可能会出现 UnsupportedEncodingException异常
System.out.println("methodB");
}
}
throw
throw关键字用于显式抛出异常,抛出的时候是抛出的是一个异常类的实例化对象.
语法:throw new 异常类构造方法
如: throw new RunTimeException();
public class Demo5 {
public static void main(String[] args) {
/*
throws:用在方法声明部分,表示次方法中有可能会出现某种类型的异常,该方法不处理异常,谁调用谁处理
throw:在方法体中,抛出一个具体的异常对象,该方法终止运行,在异常对象的构造方法中传入异常原因
*/
try {
char c= level(101);
}catch (ArithmeticException ai){
ai.printStackTrace();
System.out.println(ai.getMessage());
}finally {
System.out.println("分数错误,请重新输入");
}
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
public static char level(int socre)throws ArithmeticException{
if (socre<0|| socre>100){
throw new ArithmeticException("分数异常");//当不满足某种条件时,程序主动抛出异常对象,终止此方法继续向下执行,通过异常构造方法来传入异常原因
}
if (socre>=90){
return 'A';
}else return 'B';
}
}
运行期异常和编译期异常
编译时期异常(即checked异常、受检异常):
在代码编译阶段,编译器就能明确警示当前代码可能发生(不是一定发生)XX异常,并明确告知
程序员提前编写处理它的代码。如果程序员没有编写对应的异常处理代码,则编译器就会直接判
定编译失败,从而不能生成字节码文件。通常,这类异常的发生不是由程序员的代码引起的。
运行时期异常(即runtime异常、unchecked异常、非受检异常):
在代码编译阶段,编译器完全不做任何检查,无论该异常是否会发生,编译器都不给出任何提
示。只有等代码运行起来并确实发生了XX异常,它才能被发现。通常,这类异常是由程序员的
代码编写不当引起的。