Java---09---异常

异常:

异常概述:

异常时程序运行时代码序列中产生的一种异常情况。这里采用的名词是异常而不是错误,是为了强调发生的事件未必是一个错误,异常也可能是某些很少出现的特殊事件。也可以理解为程序在运行时出现的不正常的情况。

例如:

1.想要打开的文件不存在

2.程序执行时除数为0

3.数组下标越界

...

一个除数为0 的例子

import java.util.Scanner;

public class EXCEPTION
{
    public static void main (String[] args)
    {
        int a,b,c;
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        c = a/b;
        System.out.println(c);
    }
}

输入 10 0 在控制台会出现:

10 0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at EXCEPTION.main(EXCEPTION.java:10)

在main函数中出现了算术异常:被0除了。

这就是一个异常。

在Java中任何异常都是继承自Throwable的,Throwable分为Error和Exception,其中Error是不可恢复的错误,只有尽量不免,而Exception则是异常,是可以进行处理的。

异常的处理:try-catch-finally

try {
//需要被检测的代码
} catch (Exception e) {
// TODO: handle exception
//处理异常的代码(处理方式)
}
finally{
//一定会执行的语句
}

还是刚才的那个程序,进行处理:

import java.util.Scanner;

public class EXCEPTION
{
    public static void main (String[] args)
    {
        int a,b,c;
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        try
        {
            c = a/b;
            System.out.println(c);
        }
        catch(Exception e)
        {
            System.out.println("出现异常,分母为0");
        }
    }
}

再输入 10 0

打印结果为:

10 0
出现异常,分母为0

程序运行到 c = a/b;  的时候出现了异常,相当于新创建了一个异常类的对象 //new Exception ();

catch捕获到了这个异常,并进行处理 :System.out.println("出现异常,分母为0");

对捕获到的异常对象进行常见方法操作:

1.String getMessage()获取异常的信息

在catch语句中加上:System.out.println(e.getMessage());

显示结果为:/ by zero

2.toString

在catch语句中加上:System.out.println(e.toString());

显示结果为:

java.lang.ArithmeticException: / by zero   

显示 异常名称,异常信息

3.printStackTrace

打印堆栈中的追踪信息,此方法无返回值,不需打印,直接调用

Catch语句中,e.printStackTrace();

显示结果为:

java.lang.ArithmeticException: / by zero
at EXCEPTION.main(EXCEPTION.java:11)

显示异常名称,异常信息,异常出现的位置

其实JVM默认的异常处理机制就是调用此方法。

throw和throws

import java.util.Scanner;

class div
{
    int div (int a,int b)throws Exception//在功能上通过throes关键字声明了该功能有可能会出现问题
    {
        return a/b;
    }
}

public class EXCEPTION
{
    public static void main (String[] args)
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        c = d.div(a, b);
        System.out.println(c);
    }
}

编译不能通过。

处理方式有两种:1.捕获(try-catch),2.抛出

第一种处理方式:捕获

import java.util.Scanner;

class div
{
    int div (int a,int b)throws Exception//在功能上通过throes关键字声明了该功能有可能会出现问题
    {
        return a/b;
    }
}

public class EXCEPTION
{
    public static void main (String[] args)
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        try
        {
            c = d.div(a, b);
            System.out.println(c);
        }
        catch (Exception e)
        {
// TODO: handle exception
            System.out.println(e.toString());
        }

    }
}

第二种方式:抛出throws

import java.util.Scanner;

class div
{
    int div (int a,int b)throws Exception//在功能上通过throes关键字声明了该功能有可能会出现问题
    {
        return a/b;
    }
}

public class EXCEPTION
{
    public static void main (String[] args)throws Exception
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        c = d.div(a, b);
        System.out.println(c);
    }
}

在主函数后加 throws Exception

将异常抛给虚拟机

显示结果:

1 0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at div.div(EXCEPTION.java:6)
at EXCEPTION.main(EXCEPTION.java:25)

就相当于 将麻烦推给别人(JVM)了。

对多异常的处理:

我们在定义功能的时候有可能发生不止一个异常,需要我们对多个异常进行处理

比如说在刚才的异常的基础上,发生了数组下标越界。

class div
{
    int div (int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException
    {
        int arr[] = new int[b];
        System.out.println(arr[5]);//有可能会造成数组越界
        return a/b;
    }
}

这是该如何处理?

1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体

2.如果有多个异常,就需要对应多个catch语句进行捕获。当然只用一个catch语句,catch (Exception e)

也能实现处理,但是这样做没有针对性。

如果多个catch块中出现继承关系,父类异常catch块放在最下面。

public class EXCEPTION
{
    public static void main (String[] args)//throws Exception
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        try
        {
            c = d.div(a, b);
            System.out.println(c);
        }
        catch(ArithmeticException e)
        {
            System.out.println("00000"+"\n"+e.toString());
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
// TODO: handle exception
            System.out.println("数组下标越界"+"\n"+e.toString());
        }
    }
}

逐个测试异常是否被处理

1.

4 1
数组下标越界
java.lang.ArrayIndexOutOfBoundsException: 5

第二个catch语句处理

2.

10 0
0
00000
java.lang.ArithmeticException: / by zero

第一个catch语句处理

3.有没有可能两种情况都发生?

10 0
0
00000
java.lang.ArithmeticException: / by zero

只处理了下标越界的问题,而没有处理0的问题,这是为什么?

按照程序执行的顺序,首先执行的是 System.out.println(arr[5]);  到这里发生了异常,程序就会停止并进行处理。

自定义异常:

因为项目中有可能会出现一些没有被Java所描述并封装对象的问题,对这些问题

按照Java对问题封装的思想,进行自定义异常。

除数为0已经被Java封装,现在假定除数为负数也是异常。

自定义异常类:

class FushuException extends Exception{

}

必须是自定义类继承Exception。

继承Exception的原因:

异常体系有一个特点:

异常类和异常对象都需要被抛出,他们都具备可抛性。这个可抛性是Throwable这个体系中的独有特点。只有这个体系中的类和对象才可以被throws、throw操作。

我们自定义的异常,Java 无法识别,无法自动抛出,只能手动抛出(throw)。

当在函数内部出现throw抛出异常对象,就必须要给出对应的处理动作,要么在函数内部进行try,要么在函数上声明(throws)。

一般情况下,函数内出现异常,函数上需要声明。

代码:

import java.util.Scanner;

class FushuException extends Exception
{
}

class div
{
    int div (int a,int b)throws ArithmeticException,FushuException
    {
        if (b < 0)
            throw new FushuException();
        return a/b;
    }
}

public class EXCEPTION
{
    public static void main (String[] args)//throws Exception
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        try
        {
            c = d.div(a, b);
            System.out.println(c);
        }
        catch(ArithmeticException e)
        {
            System.out.println("00000"+"\n"+e.toString());
        }
        catch (FushuException e)
        {
// TODO: handle exception
            System.out.println("出现负数"+"\n"+e.toString());
        }
    }
}

显示结果:

3 -2
出现负数
FushuException

发现打印结果中只有异常的名称,而没有异常的信息。

以为自定义的异常并未定义信息。

如何定义异常信息?

复写getMessage方法。

class FushuException extends Exception
{
    private String s;
    public FushuException(String s)
    {
        super();
        this.s = s;
    }
    public String getMessage ()
    {
        return s;
    }
}

复写完成后,在抛异常的时候,将信息内容传递过来。

class div
{
    int div (int a,int b)throws ArithmeticException,FushuException
    {
        if (b < 0)
            throw new FushuException("出现负数");
        return a/b;
    }
}

显示结果:

3 -2
FushuException: 出现负数

这样做虽然没有问题,但是太麻烦了。

Exception都是继承自Throwable的。

Throwable中所有的方法在子类中都可以直接调用。

我们通过查API文档发现Exception类中没有定义新的方法,所有的方法都是继承自Throwable的。

所以只需将调用Exception的构造方法完成初始化,就可以调用父类中的getMessage方法。无需复写。

class FushuException extends Exception
{
    public FushuException(String s)
    {
        super(s);
    }
}

Throw和throws的区别:

Throws使用在函数上

Throw使用在函数内

Throws后面跟的是异常类,可以跟多个。

Throw后面跟的是异常对象。

RuntimeException是一个非常特殊的异常类。(运行时异常)

如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。

如果在函数上声明了该异常,调用者可以不用处理(try、throw),编译一样通过。

class div
{
    int div (int a,int b)
    {
        if (b == 0)
            throw new ArithmeticException();
        return a/b;
    }
}

class div
{
    int div (int a,int b)throws ArithmeticException
    {
//if (b == 0)
//throw new ArithmeticException();
        return a/b;
    }
}

这两种方式都可以通过编译。

之所以不用在函数上声明,是因为不需要让调用者处理。

当该异常发生,希望程序停止。因为运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修改。

自定义异常时,如果该异常的发生无法再继续进行运算的话,就让自定义的异常继承RuntimeException。

finally

finally中存放的是一定会执行的代码。

无论有没有异常,finally中的代码一定会被执行。

import java.util.Scanner;

class FushuException extends Exception
{
    private String s;
    public FushuException(String s)
    {
        super(s);
    }
}

class div
{
    int div (int a,int b)throws FushuException
    {
        if ( b < 0)
            throw new FushuException("出现负数");
        return a/b;
    }
}

public class EXCEPTION
{
    public static void main (String[] args)//throws Exception
    {
        int a,b,c;
        div d = new div();
        Scanner readScanner = new Scanner(System.in);
        a = readScanner.nextInt();
        b = readScanner.nextInt();
        try
        {
            c = d.div(a, b);
            System.out.println(c);
        }
        catch (FushuException e)
        {
// TODO: handle exception
            System.out.println(e.toString());
        }
        finally
        {
            System.out.println("finally");
        }
        System.out.println("Over");
    }
}

显示结果:

4 1
4
finally
Over
4 -2
FushuException: 出现负数
finally
Over

Over和finally都被执行了,看上去好像没什么区别。

当发生这种情况的时候:当程序出现异常时,处理完成后,程序return了,那么finall中的代码还会执行吗?Over还会执行吗?

在catch块中加return

显示结果;

4 -1
FushuException: 出现负数
finally

finally依然会执行,但是over却不会执行。

finally代码块中存放的是一定会被执行的代码。无论有没有异常都会执行。通常用于关闭资源。

Try-catch-finally语句的格式:

3个格式:

1.

try
{
}
catch (Exception e)
{
// TODO: handle exception
}

2.

try
{
}
catch (Exception e)
{
// TODO: handle exception
} finally
{
}

3.

try
{

} finally
{

}

异常在子父类覆盖中的体现;

1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者改异常的子类。

class AException extends Exception
{
}

class BException extends AException
{
}
class CException extends Exception
{
}

class Fu
{
    void show () throws AException
}

class Zi extends Fu
{
    void show ()throws AException 或者 BException
    {
    }
}

2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。

3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须进行try处理,绝对不能抛。

时间: 2024-10-23 08:47:37

Java---09---异常的相关文章

[转载]Java中异常的捕获顺序(多个catch)

http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) 转载▼ 标签: 转载 分类: 转载 原文地址:Java中异常的捕获顺序(多个catch)作者:leesa Java代码 import java.io.IOException; public class ExceptionTryCatchTest { public void doSomething(

一种隐蔽性较高的Java ConcurrentModificationException异常场景

在使用Iterator遍历容器类的过程中,如果对容器的内容进行增加和删除,就会出现ConcurrentModificationException异常.该异常的分析和解决方案详见博文<Java ConcurrentModificationException 异常分析与解决方案>和<解决ArrayList的ConcurrentModificationException>.本文展示一种隐蔽性较高的ConcurrentModificationException异常场景,并给出解决方案. 代

java中异常类与类别

异常类的层次结构: 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出).Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性,它们都在java.lang包下面. Error类标记了严重错误,类似内存溢出,虚拟机异常,等等,是不该出现的.这些错误表示故障发生于虚拟机自身.或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError).类定义错误(NoClassDefFoundError)等.这些错

Java基础—异常

一.  Exception异常 1. 概述 异常是程序在运行时出现的错误 异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象. 其实就是java对不正常情况进行描述后的对象体现. 2. Java的异常体系 1. 从图中可以看出Throwable下有两个子类,Error和Exception 对于严重的问题,java通过Error类进行描述.对Error类一般不编写针对性的代码对其进行处理. 对于非严重的,java通过Exception类进行描述.对于Ex

Java基础——异常体系

在Java中,异常对象都是派生于Throwable类的一个实例,Java的异常体系如下图所示: 所有的异常都是由Throwable继承而来,在下一层立即分解为两个分支,Error和Exception. Error错误:描述了Java运行时系统的内部错误和资源耗尽错误.一般是指虚拟机相关的问题,如系统崩溃,虚拟机出错误等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常不处理.因为如果出现这样的内部错误,除了通告用户,并尽力使程序安全地终止之外,再也无能为力了. Exception异常:Ja

Java Exception异常介绍

 一:介绍java异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的异常.因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件.当条件生成时,错误将引发异常. 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出).Throwable 指定代码中可用异常传播机制通过 Java 应用程序

Java socket异常

Java socket异常 分类: Java 2013-07-15 22:38 981人阅读 评论(0) 收藏 举报 目录(?)[+] 使用Java socket编写程序时,通常会遇到几种种异常:BindException.UnknownHostException.ConnectException.SocketTimeoutException. BindException 会发生在Socket或ServerSocket的bind()操作中,如果无法与本机指定的IP地址或端口绑定,就会抛出此异常.

Java基础——异常(2)

throws 和 throw 有什么区别? 1.位置不同:throws用在函数上,后面跟的是异常类,可以跟很多个. throw用在函数内,后面跟的是异常对象. 2.功能不同:throws用来声明异常,让调用者知道功能有可能出现问题,并由调用者可以给出预先的处理方式. throw抛出具体问题对象.执行到throw功能已经结束了,跳转到调用者(谁调用跳哪去),并将具体的问题对象抛给了调用者. 异常体系最大的特点就是体系中的类以及类产生的对象,都具备可抛性.可抛性的意思就是可以被throws和thro

Java并发编程:Java ConcurrentModificationException异常原因和解决方法

Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException异常.下面我们就来讨论以下这个异常出现的原因以及解决办法. 以下是本文目录大纲: 一.ConcurrentModificationException异常出现的原因 二.在单线程环境下的解决办法 三.在多线程环境下的解决方法 若有不

《java中异常和错误》

异常和错误的区别. 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误:它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务