媒介
在编程的时候,不免会遇到一些特别情况,这大概会导致中止,这时候就要想着在运行的过程中能不能将这个问题捕获到,方便后面办理,这时候就要引入非常这个概念了
一 非常的概念
在Java中将在代码执行过程中不正常的步伐称为非常
Throwable:是非常体系的顶层类,其派⽣出两个⼦类Error和Exception
Error(错误):指的是Java虚拟机⽆法办理的严峻问题,⽐如StackOverflowError和OutOfMemoryError,通常是JVM虚拟机内部问题
Exception(非常):非常产⽣后步伐员可以通过代码进⾏处置惩罚,使步伐继承执⾏
我们通常把Exception称为非常,Error是错误
例如:
算数非常
- public class Test {
- public static void main(String[] args) {
- System.out.println(10/0);
- }
- }
复制代码 除数不可以为0
运行结果中编译器会报出ArithmeticException算数非常
空指针非常
- //空指针异常
- public class Test {
- public static void main(String[] args) {
- int[] arr = null;
- System.out.println(arr.length);
- }
- }
复制代码 这里的arr数组是空的,不可以求其数组长度
NullPointerException空指针非常
数组下标访问非常
- //数组下标越界访问异常
- public class Test {
- public static void main(String[] args) {
- int[] arr = new int[3];
- System.out.println(arr[3]);
- }
- }
复制代码 这里的下标是[0,2],没有3下标,这时候会出现数组下标访问非常
ArrayIndexOutOfBoundsException数组下标越界访问非常
非常的分类
Java中主要分为编译时非常和运行时候非常
编译时非常(受检查非常)
字如其名,也就是在编译时候发生的非常,也叫受检查非常
在没有运行编译器也会用红色波浪线提示
例如:
这里子类重写Object父类的方法clone方法
这里说这个非常为举行捕获出来
如果没有捕获或者说明这里就会报错
下面时运行的结果,就算没有运行编译器也会用红色波浪线提示
像下面如许举行声明白就不会报错了
- public class Person{
- private String name;
- public int age;
- @Override
- //这里进行异常的声明或者捕获
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
复制代码 运行时非常(非受查非常)
在代码运行的时候编译器就会报错,在编译时并不会报错
RunTimeException以及其⼦类对应的非常,都称为运⾏时非常NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException等等,这些非常只有在运行时候才会报错,编译时可以通过的,这就是与编译时非常的区别
非常的处置惩罚
throws非常的声明
throws就是在方法中声明大概会出现的非常,用来提示编译者,但是这个只是声明,并不是将其处置惩罚
修饰符 返回值类型 ⽅法名(参数列表) throws 非常类型1,非常类型2 等等
{ }
- public class Test {
- public static void fun(int[] arr)throws Exception{
- System.out.println(arr.length);
- }
- public static void main(String[] args) throws Exception{
- int[] arr = null;
- fun(arr);
- }
- }
复制代码
这里只是声明白非常并没有处置惩罚,相当于只是将这个非常逐渐传递下去,并没有得到真正的办理
就像这里主函数调用了含有非常声明的方法,主函数也要举行声明,相当于谁利用这个方法都要声明
如果不声明编译器就会报错
- 1.throws必须跟在⽅法的参数列表之后
- 2. 声明的异常必须是Exception或者Exception的⼦类
- 3. ⽅法内部如果抛出了多个异常,throws之后必须跟多个异常类型
- 4. 如果声明多个异常是同一个父类,可以直接声明父类一异常
- 5. 但是throws并么有处理异常,只是仅仅声明了
复制代码 throw非常处置惩罚
throw new 非常类型();
- public class Test {
- public static void fun(int[] arr,int index){
- if(arr==null){
- throw new NullPointerException("空指针异常");
- }
- if(index<0||index>=arr.length){
- throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
- }
- System.out.println("后面的代码");
- }
- public static void main(String[] args) {
- int[] arr = {1,2,3};
- fun(arr,3);
- }
- }
复制代码 这里一旦非常抛出,后面的代码就不会执行了,就像这里的3是超过数组下标,以是这里会抛出数组下标非常,后面的代码不会执行
运行结果如下
- 1.throw必须在方法内部
- 2.如果是RunTimeException或者其子类可以不用处理这些会在运行时由JVM来处理
- 3.异常一旦抛出,后面的代码就不会执行了
复制代码 try - catch捕获非常
Java中为了捕获非常有了 try catch finally等关键字
- try{
- // 将可能出现异常的代码放在这⾥
- //这里要捕获的异常类型与try中的异常一致
- }catch(要捕获的异常类型 e){
- //异常处理完后,后面的代码会执行
- }catch(异常类型 e){
- // 对异常进⾏处理
- }finally{
- // finally中代码一定会执行
- }
复制代码 例如
- public class Test {
- public static void main(String[] args) {
- try{
- int[] arr = {1,2,3};
- System.out.println(arr[3]);
- }catch (NullPointerException e){
- e.printStackTrace();//处理异常
- }catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace();
- }
- //异常被捕获以后后面的代码会正常执行
- System.out.println("后面的代码执行了");
- }
- }
复制代码 这里是下标越界的非常,被捕获了处置惩罚了,如果没有捕获,这里后面的代码就不会执行了
运行结果如下
例如下面如果没有捕获和处置惩罚非常,非常后面的代码不会执行
就像这里try中放的是出现的是数组下标访问非常,而我们这里捕获的是空指针非常,以是这里并不会处置惩罚非常,因今后面的代码就不执行了
那这时候可以在其后面放其大概出现非常的父类举行捕获,如许就不会出现如许的问题了
- public class Test {
- public static void main(String[] args) {
- try{
- int[] arr = {1,2,3};
- System.out.println(arr[3]);
- }catch (NullPointerException e){
- e.printStackTrace();
- }catch (Exception e){//可以捕捉所有异常,因为其是异常的父类
- e.printStackTrace();
- }
-
- System.out.println("后面的代码执行了");
- }
- }
复制代码 这里的空指针非常和数组下标访问非常都是Exception的子类,可以在后面放父类非常,防止没有捕获到
运行结果如下
但是不发起只是用父类Exception来举行捕获,以是尽量将其放在末了举行捕获父类非常,用起来兜底,防止自己没有考虑全面
try如果捕获到了非常,其try中后面的代码就不会执行了
- try - catch注意事项
- 1.try中的异常如果被捕获到了异常,try中异常之后的代码不会执行
- 2.catch捕获的异常与抛出类型的异常不匹配,异常就不会被捕获
- 3.异常之间也有父子关系,捕获子类异常在捕获父类异常之后
复制代码 finally关键字
有些时候我们需要一些代码是必须要执行到,无论是存在否非常,一些步伐都要执行,那因此就要引出finally关键字
- 语法格式:
- try{
- // 可能会发⽣异常的代码
- }catch(异常类型 e){
- // 对捕获到的异常进⾏处理
- }finally{
- // 此处的语句⽆论是否发⽣异常,都会被执⾏到
- }
复制代码- public class Test {
- public static void main(String[] args) {
- try{
- int[] arr = {1,2,3};
- System.out.println(arr[3]);
- }catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace();
- }
- finally {
- System.out.println("finally中的代码被执行了");
- }
- System.out.println("后面的代码执行了");
- }
- }
复制代码 这里finally中的语句会执行,try-catch中的语句会执行
运行结果如下
既然都可以执行,那为什么还要finally语句呢
- public class Test {
- public static int fun(){
- Scanner scanner = new Scanner(System.in);
- try {
- int sc = scanner.nextInt();
- return sc;
- }catch (InputMismatchException e){
- e.printStackTrace();
- }finally {
- System.out.println("finally中的代码");
- }
- System.out.println("最后面的代码");
- scanner.close();
- return 0;
- }
- public static void main(String[] args) {
- int n = fun();
- System.out.println(n);
- }
复制代码 这里就算有return 语句,finally中代码一定会被执行,而try-catch-finally后面的代码不会执行了
- 1.先执行try中的代码
- 2.如果try中的代码有异常,那就在try中后面代码不会执行,在catch寻找是否有
- 与try中异常相匹配的
- 3.如果没有在catch中匹配到对应异常,如果没有异常将会向上传递
- 4.上层如果也没有处理异常,异常将会继续向上传递,一直到main函数为止
- 5.无论是否匹配到异常,finally中的代码都会被执行
复制代码 四 自定义非常
固然Java提供了很多非常,偶然候一些非常不能满足我们的需求,这是我们就可以自定义非常来满足需求
这里我们模仿实现一个用户名和密码的登录
- public class Test {
- private String userId = "三三";
- private String password = "060610";
- public void login(String userId,String password) {
- if(!this.userId.equals(userId)){
- System.out.println("用户名错误");
- }
- if(!this.password.equals(password)){
- System.out.println("密码错误");
- }
- System.out.println("登录成功");
- }
- public static void main(String[] args) {
- Test test = new Test();
- test.login("三三","060610");
- }
- }
复制代码 这里密码和用户名都精确,这里会登录乐成
运行结果如下
那我们可以在其用户名错误或者密码错误的时候抛出非常吗
当然可以,这时候我们就要自定义一个非常,然后继承Exception或者RunTimeException
下面是两个自定义非常类
- //继承基类异常
- //用户名异常
- //这里继承的是受查异常
- class UserIdException extends Exception{
- public UserIdException(String message){
- super(message);
- }
- }
- //密码异常
- class PasswordException extends Exception{
- public PasswordException(String message){
- super(message);
- }
- }
复制代码 Test类中的代码利用上面的自定义非常
- class UserIdException extends Exception{
- public UserIdException(String message){
- super(message);
- }
- }
- class PasswordException extends Exception{
- public PasswordException(String message){
- super(message);
- }
- }
- public class Test {
- private String userId = "三三";
- private String password = "060610";
- public void login(String userId,String password) {
- try {
- if(!this.userId.equals(userId)){
- throw new UserIdException("用户名错误"+userId);
- }
- if(!this.password.equals(password)){
- throw new PasswordException("密码错误"+password);
- }
- //如果没有异常就会登录成功
- System.out.println("登录成功");
- }catch (UserIdException e){
- e.printStackTrace();
- }catch (PasswordException e){
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- Test test = new Test();
- test.login("三三","060610");
- }
- }
复制代码 这里用户名和密码都精确,以是是登录乐成
如果用户名不对,就会爆出用户名非常,登录就不乐成
自定义非常都是继承Exception或者RunTimeException
继承Exception就是受查非常(编译时非常)
继承RunTimeException就是非受查非常(运行时非常)
到这里就结束了,预知后事如何,请听下回分解
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |