您的位置:首页 > 文旅 > 旅游 > 别样海外购怎么开店_庆阳字体设计_广告推广计划_成都网站建设系统

别样海外购怎么开店_庆阳字体设计_广告推广计划_成都网站建设系统

2024/12/23 2:31:08 来源:https://blog.csdn.net/2301_79985750/article/details/142927869  浏览:    关键词:别样海外购怎么开店_庆阳字体设计_广告推广计划_成都网站建设系统
别样海外购怎么开店_庆阳字体设计_广告推广计划_成都网站建设系统

异常机制

异常机制指的是程序出现错误时,程序的处理方式。

程序的错误分为三种:

  • 编译错误:由于没有遵循对于语言的语法规则,编辑器可以自动发现并提示的错误位置和原因。
  • 逻辑错误:程序没有按照预期的顺序执行。
  • 运行时错误:程序执行过程中,运行环境发现不能执行的操作,而异常就是指的程序运行时发生的错误。

走进异常

例子:算数异常+数组下标越界异常+空指针异常

public static void main(String[] args) {System.out.println(10/0);    // 算数异常
// ----------------------------------------int[] a = {1,2,3,4,5};    // 数组下标越界异常System.out.println(a[10]);
// ----------------------------------------int[] a = null;    // 空指针异常System.out.println(a[0]);}

 上述的代码在分别运行时均会抛出异常,且抛出异常后不会去执行下面的代码。如下图

以空指针异常为例,根据空指针异常的源码,可以知道异常其实就是一个个类

异常的体系结构: 

在Java中,所有的异常都有一个共同的祖先:Throwable(可抛出),Throwable有两个子类,分别为Error(错误)和Exception(异常),它们两者的区别是:Error不能够被处理,但是Exception可以被程序本身所处理。

Error(错误):是程序无法处理的错误,表示运行程序中较严重的问题。大多数错误与代码的编写者执行的操作无关,而表示代码运行时JVM出现的问题。因此我们在编写程序时不必关心这一类错误。常见的有StackOverflowError(栈溢出),NOClassDefFoundError(类定义错误)

Exception(异常):是程序本身可以处理的异常。在编写程序时我们要尽可能的去处理这些异常。有一个重要的子类RuntimeException。它以及它的子类表示jvm常用操作引发的异常。例如开头提到的算数异常,数组越界异常以及空指针异常。主要分为两大类:运行时异常和编译时异常(非运行时异常)

  • 运行时异常:时RuntimeException类及其子类的异常,这些异常称为非受查异常,程序可以选择处理,或者不进行处理。一般是由程序的逻辑错误导致,例如:数组下标越界,在编写程序时,应当尽可能的避免这类情况的发生。
  • 编译时异常:RuntimeException以外的异常,这些都是必须在编译前必须处理的异常,如果不进行处理,那么编译时就不会通过。

通常,Java中的异常(Throwable)分为两大类:受查异常和非受查异常:

  • 受查异常:除了Error类和RunTimeException类及其子类以外的所有类,在编译期间抛出,如何不进行处理,代码不会通过编译,当程序出现这里异常,要么使用try-catch语句进行捕获,要么用throw进行抛出
  • 非受查异常:包括Error类和RunTimeException类及其子类,一般是对代码进行修改(因为大部分是代码本身的出错)而不是去捕获它们。

异常的处理

关键词throw:

异常可以通过jvm自动抛出,也可以通过程序员通过throw手动抛出。例如抛出一个自定义异常:

public class Main {public static void test(int a) {if(a == 1) {throw new ArithmeticException("a == 1");}}public static void main(String[] args) {test(1);}
}

表示如果是传入的是1,那么就会抛出算数异常(可以传参,也可以不传参),异常信息为a==1.

注意事项:

  1. throw必须写在方法体的内部。
  2. 抛出的对象必须是Exception或者Exception的子类对象。
  3. 如果抛出的是RunTimeException或者RunTimeException,则可以不用处理,直接交给jvm进行处理。
  4. 异常一旦抛出,后面的代码不会执行。

关键词throws:

语法:修饰符 返回类型 方法名(参数) throws 异常类型1,异常类型2...{
}

throws其实并没有处理异常,只是告诉调用此方法可能会抛出相对应的异常,交给了此方法的调用者进行处理,如果不进行处理,不断的throws,知道交给jvm进行处理,此时程序就会终止
例如: throws CloneNotSupportedException就是声明main方法和clone方法可能会抛出的异常

class Person implements Cloneable {@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class test1 {public static void main(String[] args) throws CloneNotSupportedException {Person person = new Person();Person person1 = (Person) person.clone();}
}

注意:

  1. throws必须位于方法的参数列表之后
  2. throws后的异常必须是Exception类及其子类
  3. 如果throws语句异常存在父子关系,只需要保留父类即可
  4. throws并没有真正的处理异常,只是将异常抛出给上层的调用者,最终交给jvm处理

关键词:try-catch:

try{
        // 异常的代码
}catch(异常的类型 变量){

}

其中try内部写可能出现异常的代码,catch用于捕获指定的异常;如果try内部出现异常,catch进行捕获,捕获成功执行catch内部的代码,捕获失败,程序终止并报错。

public class Main {public static void test(int a) throws CloneNotSupportedException{if(a == 1) {throw new CloneNotSupportedException();}}public static void main(String[] args) {try {test(1);System.out.println("没有抛出异常");}catch (CloneNotSupportedException e) {System.out.println("捕获了异常");}System.out.println("程序到末尾");}
}

向test传参整形1,进入if语句,throw抛出异常,catch进行异常的捕获,最终执行打印:
捕获了异常,程序到末尾,但是如果注释掉if了的throw语句,那么就不会抛出异常,那么就不会被捕获,因此执行打印:没有抛出异常,程序到了末尾。


当打印了异常信息后,可能难以发现异常信息的出现位置,这是可以用到catch里面的变量信息e,利用e.printStackTrace()栈信息的打印,可以帮助追踪到出错位置;

public class Main {public static void test(int a) throws CloneNotSupportedException{if(a == 1) {throw new CloneNotSupportedException();}}public static void main(String[] args) {try {test(1);System.out.println("进入try");}catch (CloneNotSupportedException e) {System.out.println("捕获了异常");e.printStackTrace();}System.out.println("程序到末尾");}
}

由于PrintStackTrace打印逻辑不基于println,因此程序到末尾不是最后打印。

当一个程序可能出现多个异常时,需要多个catch语句进行捕获。

    public static void main(String[] args) {int[] arr = {1,2,3};try {System.out.println(arr[1]);arr = null;System.out.println(arr.length);}catch (ArrayIndexOutOfBoundsException e) {System.out.println("处理 ArrayIndexOutOfBoundsException 异常");e.printStackTrace();}catch (NullPointerException e) {System.out.println("处理 NullPointerException 异常");e.printStackTrace();}System.out.println("-----------------------------------");}

这里时空指针异常,用第二个catch进行捕获。

 但是不会一下子抛出多个异常,因为当捕获到一个异常后,catch进行处理,后面的异常不会被捕获

一些不规范的异常抛出

1.存在一个catch语句并且待捕获异常为Exception,通过一个catch捕获所有,这样子写不能搞清楚到底是抛出了那些异常。但是Exception可以兜底。

public static void main(String[] args) {int[] arr = {1,2,3};try {System.out.println(arr[4]);}catch (Exception e) {System.out.println("处理 Exception 异常");e.printStackTrace();}}// ----------------------------------------------------------public static void main(String[] args) {int[] arr = {1,2,3};try {System.out.println(arr[4]);}catch (NullPointerException e) {System.out.println("处理 NullPointerException 异常");e.printStackTrace();}catch (Exception e) {System.out.println("处理 Exception 异常,兜底");e.printStackTrace();}}

2.存在一个catch语句并且捕获多个异常,用|进行连接,和上述相同,分不清到底抛出什么异常

public static void main(String[] args) {int[] arr = {1,2,3};try {System.out.println(arr[4]);}catch (ArrayIndexOutOfBoundsException | NullPointerException e) {System.out.println("处理 ArrayIndexOutOfBoundsException | NullPointerException 异常");e.printStackTrace();}}

3.前面的catch捕获Exception,后面的catch捕获了Exception的子类

public static void main(String[] args) {int[] arr = {1,2,3};try {System.out.println(arr[4]);}catch (Exception e) {System.out.println("处理 Exception 异常");e.printStackTrace();}catch (NullPointerException e) {System.out.println("处理 NullPointerException 异常");e.printStackTrace();}}

总结:

  1. try块内出现异常位置后的语句不会被执行
  2. 抛出的异常与catch不匹配,一直向上抛出,直到抛给jvm进行处理
  3. try中多个异常可以用多个catch进行一一捕获,可以用Exception进行兜底,但是不推荐直接用Exception
  4. 当catch出现父子关系,子类在上,父类在下

关键字:finally

在编写代码的过程中,有些代码无论是否发生异常都需要被执行,比如程序中打开的资源:网络连接,数据库,在程序正常或者异常退出时,必须对资源进行回收,另外,异常会引发程序的跳转,导致语句无法执行,针对这些语句,Java提供了finally关键字,和try-catch组合为try-catch-finally进行一起使用

public static int getData() {Scanner sc = null;try {sc = new Scanner(System.in);int data = sc.nextInt();return data;}catch (InputMismatchException e) {e.printStackTrace();}finally {System.out.println("finally中的代码");if(sc!=null) {sc.close();}}return 0;}public static void main(String[] args) {int data = getData();System.out.println(data);}

getData()方法为了获取整数,没有获取到,抛出异常,return 0,获取到打印获取的整数,无论是否成功获取,都会执行finally中的代码,其中.close()为了释放资源。
另一种方式,可以不写close().
try后面实现了一个AutoCloseavable或Closeable接口的资源,Java运行时会在try块执行完毕后自动调用close方法

public static int getData() {try (Scanner sc = new Scanner(System.in)){int data = sc.nextInt();return data;}catch (InputMismatchException e) {e.printStackTrace();}finally {System.out.println("finally中的代码");}return 0;}

避免在finally中出现return语句

    public static int test() {try {return 10;}catch (NullPointerException e) {e.printStackTrace();}finally {return 20;}}public static void main(String[] args) {System.out.println(test());}

执行顺序:

  1. test执行,进入try。
  2. 执行return 10,但是try块中的return 语句实际返回值之前必须先执行finnaly。
  3. 执行finnaly,return 20,结束test方法,返回20
  4. 打印出20

throw和throws

  1. throw用于实际抛出的语句,throws表示该方法可能抛出的异常
  2. throw后面跟实例,throws后面跟异常类型
  3. throw可以用在任何方法体内,但是throws只能用在方法声明上

异常的处理流程

  1. 程序执行try中的代码
  2. 如果try中出现异常,结束执行try中的代码,catch进行捕获
  3. 如果捕获成功,执行catch中的代码,捕获失败向上传递给调用者,如果直到main方法没有合合适的代码处理异常,交给jvm,此时程序异常终止。
  4. 无论是否捕获成功,finally都会正常执行

自定义异常

在实际的开发中,Java中的异常不能完全表示遇到的一些异常,这是就需要自定义一些异常类来满足开发的需求。

我们根据空指针异常的源码对于自定义异常进行仿写

由此可得:

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

那么总的实现是:
 

public class Login {private String userName;private String passWord;public void setUserName(String userName) {this.userName = userName;}public void setPassWord(String passWord) {this.passWord = passWord;}public void loginInfo(String userName, String passWord) throws userNameException, PassWordException {if(!this.userName.equals(userName)) {throw new userNameException("用户名错误!");}if(!this.passWord.equals(passWord)) {throw new PassWordException("密码错误!");}System.out.println("登录成功!");}
}
import java.util.Scanner;
class Test {public static void main(String[] args) {Login login = new Login();Scanner scanner = new Scanner(System.in);login.setUserName("abc");login.setPassWord("123");try {System.out.println("请输入用户名:");String userName = scanner.nextLine();System.out.println("请输入密码:");String passWord = scanner.nextLine();login.loginInfo(userName, passWord);}catch (userNameException e) {System.out.println("用户名错误!");e.printStackTrace();}catch (PassWordException e) {System.out.println("密码错误!");e.printStackTrace();}finally {scanner.close();}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com