Java中的异常(抛出异常、自定义异常等)

简介: Java中的异常(抛出异常、自定义异常等)

抛出处理

定义一个功能,进行除法运算例如(div(int x,int y))如果除数为0,进行处理。
功能内部不想处理,或者处理不了。就抛出使用throw new Exception("除数不能为0"); 进行抛出。抛出后需要在函数上进行声明,告知调用函数者,我有异常,你需要处理如果函数上不进行throws 声明,编译会报错。例如:未报告的异常 java.lang.Exception;必须对其进行捕捉或声明以便抛出throw  new Exception("除数不能为0");
public static void div(int x, int y) throws Exception { // 声明异常,通知方法调用者。

    if (y == 0) {
throw new Exception("除数为0"); // throw关键字后面接受的是具体的异常的对象
    }
    System.out.println(x / y);
    System.out.println("除法运算");
}

main方法中调用除法功能

调用到了一个可能会出现异常的函数,需要进行处理。
        1:如果调用者没有处理会编译失败。
如何处理声明了异常的函数。
        1:try{}catch(){}

public static void main(String[] args) {

    try {
        div(2, 0);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("over");

}

public static void div(int x, int y) throws Exception { // 声明异常,通知方法调用者。

    if (y == 0) {
throw new Exception("除数为0"); // throw关键字后面接受的是具体的异常的对象
    }
    System.out.println(x / y);
    System.out.println("除法运算");
}

}

                        2:继续抛出throws 

class Demo9 {

public static void main(String[] args) throws Exception {
    div(2, 0);
    System.out.println("over");
}

public static void div(int x, int y) throws Exception { // 声明异常,通知方法调用者。
if (y == 0) {
    throw new Exception("除数为0"); // throw关键字后面接受的是具体的异常的对象
}

    System.out.println(x / y);
    System.out.println("除法运算");
}

}

throw和throws的区别

1.相同:都是用于做异常的抛出处理的。
2.不同点:
1.使用的位置: throws 使用在函数上,throw使用在函数内
2.后面接受的内容的个数不同:
1.throws 后跟的是异常类,可以跟多个,用逗号隔开。
2.throw 后跟异常对象。
//throws 处理
public static void main(String[] args) throws InterruptedException {

    Object obj = new Object();
    obj.wait();

}


public static void main(String[] args) {

    //try catch 处理
    Object obj = new Object();
    try {
        obj.wait();
    } catch (InterruptedException e) {
        
        e.printStackTrace();
    }

}

总结
1.try语句不能单独存在,可以和catch、finally组成 try...catch...finally、try...catch、try...finally三种结构。
2.catch语句可以有一个或多个,finally语句最多一个,try、catch、finally这三个关键字均不能单独使用。
3.try、catch、finally三个代码块中变量的作用域分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
4.多个catch块时候,Java虚拟机会匹配其中一个异常类或其子类,就执行这个catch块,而不会再执行别的catch块。(子类在上,父类在下)。
5.throw语句后不允许有紧跟其他语句,因为这些没有机会执行。
6.如果一个方法调用了另外一个声明抛出异常的方法,那么这个方法要么处理异常,要么声明抛出。

自定义异常

问题:现实中会出现新的病,就需要新的描述。
分析: java的面向对象思想将程序中出现的特有问题进行封装。
案例:  定义功能模拟凌波登录。(例如:lb(String ip))需要接收ip地址

1.当没有ip地址时,需要进行异常处理。

  1. 当ip地址为null是需要throw new Exception("无法获取ip");

    1. 但Exception是个上层父类,这里应该抛出更具体的子类。
    1. 可以自定义异常

2.自定义描述没有IP地址的异常(NoIpException)。

  1. 和sun的异常体系产生关系。继承Exception类,自定义异常类名也要规范,结尾加上Exception,便于阅读

/*
自定义异常
*/
class NoIpException extends Exception {

NoIpException() {

}

NoIpException(String message) {
    super(message);
}

}

class Demo10 {

public static void main(String[] args) throws NoIpException {

    System.out.println();
    String ip = "192.168.10.252";
    ip = null;
    try {
        Lb(ip);
    } catch (NoIpException e) {
        System.out.println("程序结束");
    }

}

/*
 * 
 * 凌波教学
 */
public static void Lb(String ip) throws NoIpException {
    if (ip == null) {
        // throw new Exception("没插网线吧,小白");
        throw new NoIpException("没插网线吧,小白");
    }

    System.out.println("醒醒了,开始上课了。");
}

}

案例:模拟吃饭没带钱的问题
1.定义吃饭功能,需要钱。(例如:eat(double money))
2.如果钱不够是不能吃放,有异常。
3.自定义NoMoneyException();继承Exception 提供有参无参构造,调用父类有参构造初始化。at 方法进行判断,小于10块,throw NoMoneyException("钱不够");
4.eat 方法进行声明,throws NoMoneyException
5.如果钱不够老板要处理。调用者进行处理。try{}catch(){} 。
class NoMoneyException extends Exception {

NoMoneyException() {

}

NoMoneyException(String message) {
    super(message);
}

}

class Demo11 {

public static void main(String[] args) {

    System.out.println();
    try {
        eat(0);
    } catch (NoMoneyException e) {
        System.out.println("跟我干活吧。");
    }
}

public static void eat(double money) throws NoMoneyException {
    if (money < 10) {
        throw new NoMoneyException("钱不够");
    }
    System.out.println("吃桂林米粉");
}

}

运行时异常和非运行时异常

RuntimeException

RunntimeException的子类:

            ClassCastException
                多态中,可以使用Instanceof 判断,进行规避
            ArithmeticException
                进行if判断,如果除数为0,进行return
            NullPointerException
                进行if判断,是否为null
            ArrayIndexOutOfBoundsException
                使用数组length属性,避免越界
            这些异常时可以通过程序员的良好编程习惯进行避免的

1:遇到运行时异常无需进行处理,直接找到出现问题的代码,进行规避。

                2:就像人上火一样牙疼一样,找到原因,自行解决即可
                3:该种异常编译器不会检查程序员是否处理该异常
                4:如果是运行时异常,那么没有必要在函数上进行声明。
            6:案例
                1:除法运算功能(div(int x,int y))
                2:if判断如果除数为0,throw new ArithmeticException();
                3:函数声明throws ArithmeticException
                4:main方法调用div,不进行处理
                5:编译通过,运行正常
                6:如果除数为0,报异常,程序停止。
                7:如果是运行时异常,那么没有必要在函数上进行声明。

1:Object类中的wait()方法,内部throw了2个异常 IllegalMonitorStateException InterruptedException
1:只声明了一个(throws) IllegalMonitorStateException是运行是异常没有声明。
class Demo12 {

public static void main(String[] args){
    div(2, 1);
}

public static void div(int x, int y) {
    if (y == 0) {
        throw new ArithmeticException();  
    }
    System.out.println(x / y);
}

}

非运行时异常(受检异常)

如果出现了非运行时异常必须进行处理throw或者try{}catch(){}处理,否则编译器报错。

        1;IOException  使用要导入包import java.io.IOException;
                2:ClassNotFoundException
            2;例如人食物中毒,必须进行处理,要去医院进行处理。
            3:案例
                1:定义一测试方法抛出并声明ClassNotFoundException(test())
                2:main方法调用test
                3:编译报错
                    1:未报告的异常 java.lang.ClassNotFoundException;必须对其进行捕捉或声明以便抛出

public void isFile(String path){

    try
    {
        /*
        根据文件的路径生成一个文件对象,如果根据该路径找不到相应的文件,
        则没法生成文件对象。
        */
        File file = new File(path);
        //读取文件的输入流
        FileInputStream input = new FileInputStream(file);
        //读取文件
        input.read();
    }
    catch (NullPointerException e)
    {
        System.out.println("读取默认的文件路径..");
    }
    
}

            4:Sun 的API文档中的函数上声明异常,那么该异常是非运行是异常,

调用者必须处理。

            5:自定义异常一般情况下声明为非运行时异常
    2:函数的重写和异常
        1:运行时异常
            1:案例定义Father类,定义功能抛出运行是异常,例如(test() throw 

ClassCastException)

            2:定义Son类,继承Father类,定义test方法,没有声明异常
            3:使用多态创建子类对象,调用test方法
            4:执行子类方法

1:函数发生了重写,因为是运行时异常,在父类的test方法中,可以声明throws 也可以不声明throws
class Father {

void test() throws ClassCastException { // 运行时异常
    System.out.println("父类");
    throw new ClassCastException();
}

}

class Son extends Father {

void test() {
    System.out.println("子类");
}

}
class Demo14 {

public static void main(String[] args) {
    Father f = new Son();
    f.test();
}

}

2:非运行时异常

1:定义父类的test2方法,抛出非运行时异常,例如抛出ClassNotFoundException

            1:此时父类test2方法必须声明异常,因为是非运行时异常
            2:Son类定义test2 方法,抛出和父类一样的异常,声明异常
            3:使用多态创建子类对象,调用test方法,调用test2方法,

1:声明非运行时异常的方法,在调用时需要处理,所以在main方法调用时throws

                2:实现了重写,执行子类的test2方法
        3:总结子类重写父类方法可以抛出和父类一样的异常,或

者不抛出异常。
// 1 子类覆盖父类方法父类方法抛出异常,子类的覆盖方法可以不抛出异常
class Father {

void test() throws ClassNotFoundException { // 非运行时异常
    System.out.println("父类");
    throw new ClassNotFoundException();
}

}

class Son extends Father {

void test() {
    System.out.println("子类");
    // 父类方法有异常,子类没有。
}

}
class Demo14 {

public static void main(String[] args) throws ClassNotFoundException  {
    Father f = new Son();
    f.test();

}

}

        4:子类抛出并声明比父类大的异常例如子类test2方法抛出Exception 
                1:编译失败,无法覆盖
                2:子类不能抛出父类异常的父类。
                3:总结子类不能抛出比父类的异常更大的异常。

//2:子类覆盖父类方法不能比父类抛出更大异常
class Father {

void test() throws Exception {
    // 非运行时异常
    System.out.println("父类");
    throw new Exception();
}

}

class Son extends Father {

void test() throws ClassNotFoundException { // 非运行时异常
    System.out.println("子类");
    throw new ClassNotFoundException();
}

}
class Demo14 {

public static void main(String[] args) throws Exception {
    Father f = new Son();
    f.test();

}

}

        3:总结
            1:子类覆盖父类方法是,父类方法抛出异常,子类的覆盖方法可以不抛

出异常,或者抛出父类方法的异常,或者该父类方法异常的子类。

            2:父类方法抛出了多个异常,子类覆盖方法时,只能抛出父类异常的子

            3:父类没有抛出异常子类不可抛出异常
                1:子类发生非运行时异常,需要进行try{}catch的(){}处理,不能

抛出。

            4:子类不能比父类抛出更多的异常

finally

    1: 实现方式一:
try{ // 可能发生异常的代码 } catch( 异常类的类型 e ){ // 当发生指定异常的时候的处理代码 }catch...        
             比较适合用于专门的处理异常的代码,不适合释放资源的代码。
    2:实现方式二:
         try{  } catch(){} finally{ // 释放资源的代码 }
         finally块是程序在正常情况下或异常情况下都会运行的。
        比较适合用于既要处理异常又有资源释放的代码
    3:实现方式三
        try{  }finally{ // 释放资源 }
         比较适合处理的都是运行时异常且有资源释放的代码。
    4:finally:关键字主要用于释放系统资源。
             1:在处理异常的时候该语句块只能有一个。
         2:无论程序正常还是异常,都执行finally。
    5:finally是否永远都执行?
        1:只有一种情况,但是如果JVM退出了System.exit(0),finally就不执行。
        2:return都不能停止finally的执行过程。
    6:案例使用流
        1:使用FileInputStream加载文件。 
            导包import java.io.FileInputStream;
        2:FileNotFoundException  
            导入包import java.io.FileNotFoundException;
        3:IOException
            import java.io.IOException;
public class FinallyDemo {
    // 本例子使用finally 关闭系统资源。
    public static void main(String[] args) {

        FileInputStream fin = null;
        try {
            System.out.println("1创建io流可能出现异常");
            fin = new FileInputStream("aabc.txt"); // 加载硬盘的文本文件到内存,通过流
            // System.out.println(fin);
        } catch (FileNotFoundException e) {
            System.out.println("2没有找到abc.txt 文件");
            System.out.println("3catch 了");
            // System.exit(0);
            // return;
        }
        // finally
        finally {
            System.out.println("4fianlly执行");
            if (fin != null) { // 如果流对象为null 流对象就不存在,没有必要关闭资源
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("close 异常");
                }

            }
            System.out.println("5finally over");
        }
        System.out.println("6mainover");
    }
}

// 2:无论程序正常还是异常,都执行finally。 但是遇到System.exit(0); jvm退出。
// finally用于必须执行的代码, try{} catch(){}finally{}
// try{}finally{}
``
相关文章
|
1月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
61 1
|
1月前
|
Java API 调度
如何避免 Java 中的 TimeoutException 异常
在Java中,`TimeoutException`通常发生在执行操作超过预设时间时。要避免此异常,可以优化代码逻辑,减少不必要的等待;合理设置超时时间,确保其足够完成正常操作;使用异步处理或线程池管理任务,提高程序响应性。
65 12
|
1月前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
36 1
|
13天前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
77 34
|
1月前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
70 7
|
1月前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
73 6
|
1月前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
57 14
|
1月前
|
Java
Java异常捕捉处理和错误处理
Java异常捕捉处理和错误处理
64 1
|
1月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
62 2
|
1月前
|
Java
如何在 Java 中处理“Broken Pipe”异常
在Java中处理“Broken Pipe”异常,通常发生在网络通信中,如Socket编程时。该异常表示写入操作的另一端已关闭连接。解决方法包括:检查网络连接、设置超时、使用try-catch捕获异常并进行重试或关闭资源。
109 5