【JAVA】笔记(11)--- 精讲异常(附枚举);

异常:

一.什么是异常?异常处理机制有什么作用?

程序在执行时发生了我们不想发生的异常情况,这种情况叫做异常;java语言的特性之一 --- 健壮性的实现主要就是靠异常处理机制,当程序执行过程中发生了异常,系统将异常信息打印到控制台上,程序员根据异常信息就可以对程序进行进一步的修改,进而使程序更加的健壮;

注意:异常也是一种类,系统内置有很多不同的异常类对应不同的异常情况,我们同样可以根据我们的需求来定义不同的异常类,来处理不同的异常情况;


二.异常的体系结构:

【JAVA】笔记(11)--- 精讲异常(附枚举);

Throwable:java 中所有异常和错误的父类;

Error:程序员无法解决处理的错误情况(跟咱们没关系,不用管);

Exception: 程序本身可以捕获并且可以处理的异常情况;其中又分为运行时异常(RuntimeException)(又称作不受检异常)和编译时异常(IOException)(又称作受检异常);

运行时异常:空指针异常,数组下标越界异常等;运行时异常我们一般不利用异常处理机制对其进行处理,解决办法就是直接修改代码;

编译时异常:编译时异常必须对其处理否则无法运行;


三.异常的抓抛:

1.异常的抛出:

如果程序在运行过程中执行某段代码时发生了异常,那么系统(JVM)将会根据异常的类型,在异常发生处创建对应的异常类型的对象并抛出,抛出给程序的调用者,并且本段代码所属的方法体中异常后的代码将不再运行;

注意:这里的异常有可能是系统内置的异常,也有可能是我们手动抛出(throw)的的异常(我们定义的异常类);

2.异常的抓取:

对于异常的发生,有俩种处理方式。第一种,调用“ try-catch-finally ”语句来抓取异常;第二种,上抛(throws)给异常发生的方法的调用者;


四.try-catch-finally:

1.try 方法体内放置可能会出现异常的代码,如果异常发生,就会 new 出一个异常类,此异常类会与 catch 的异常类型进行匹配,匹配成功,执行 catch 方法体内的代码(代码一般为打印异常的基本信息或打印异常的详细信息),匹配不成功,继续匹配后面不同的 catch ,最后finally 方法体内的代码最终一定会执行;

2.catch 多个异常类时,如果存在有继承关系的类,一定要按从子类到父类的顺序来 catch,因为如果第一个就 catch 最大的父类,那么可能执行的异常处理代码并非我们想要的;如果无继承关系,自然顺序就无所谓了;

3.catch 方法内常用的异常处理方法:

1) 异常 . getMessage ( ) ;

// 返回值为异常的基本信息(throw new 异常 ( "返回值就是这里的字符串哟" ) );一般搭配 System . out . println ( ) 打印输出信息;

2) 异常 . printSrackTrace ( ) ;

// 打印异常的详细信息(堆栈追踪信息),如:

com.bjpowernode.javase.day1.WeaponIndexOufException: 武器库装备已达上限,[Lcom.bjpowernode.javase.day1.Weapon;@7f31245a无法载入武器库系统
	at com.bjpowernode.javase.day1.Army.addWeapon(Army.java:19)
	at com.bjpowernode.javase.day1.武器系统.main(武器系统.java:12)

//第一行为异常的基本信息;

//第二行为异常出现的地方(是第三行中的异常出现的果);

//第三行也就是最后一行,为第一个异常出现的地方,是第二行异常出现的因;

注意:异常的详细信息要从下往上看,因为异常一般会存在因果关系;

4.finally 内的代码优先级仅次于 System . exit ( 0 ) ;

//强制关闭退出 JVM ,所以 finally 内的代码不会执行;即使try内有 return 语句,在try方法强制结束之前, 也会先执行 finally 内的代码;

注意:

1)在 try 内声明的变量,出了 try ,系统就不认识了,解决方法是在 try 外声明变量并初始化,在 try 内赋值,所以要理解 try 内装的是一个“ 模块 ”,一个可能会出现异常的代码模块; 

2)try-catch-finally 也可以嵌套使用;

2)有 try ,必须有 finally / catch ,finally,catch 也不可以离开 try ;


五.throw -throws , try-catch-finally:

1.throw:手动抛出异常;一般这样使用:

throw new XXXException("异常基本信息");//XXX代表是什么异常

2.throws:将“ 抛出的异常 ”捕获并上交给方法的调用者;可以 throws 多个异常;一般这样使用;

public void fangFa () throws XXXException{     //throws 的异常即为 方法体内 throw的异常
	throws new XXXException("异常基本信息");
}

3.对于“ 抛出(throw)的异常 ” 有俩种处理方式:

第一种,继续上抛给方法的调用者,但其实并没有真正的解决异常,如果一直上抛到 main 方法,都没有 try catch 异常,main 方法会继续上抛到JVM,然后程序到此结束;第二种,直接在异常发生的方法内进行try catch 处理;

那么在日常开发中,究竟该如何选择俩者的处理方式呢?

1)第一种情况,异常发生方法为子类重写父类的方法,然而对应的父类方法并没有 throws 异常,所以子类中重写的方法就不能选择 throws 了,只能*在此方法中就地解决(try - catch);

2)第二种情况,异常发生的方法属于被调用的方法,而且调用此方法的方法也是被调用的,上面还有更多更多的方法,一直到最初的执行方法,这种存在层层递进,相互关联的方法,一般选择将所有异常都 thows 给最初的调用者方法,然后在此方法中统一对所有异常进行处理;

3)注意: try-catch 和 throws 在方法中不要同时使用,因为只要使用 try-catch 就已经将异常处理掉了,再 throws 没有任何意义;


六.栗子老师:

public class pra {
    public static void main(String[] args) {
        People p=new People("王狗蛋");
        Food food=new Food("粑粑");
        try{
            p.eat(food);
        }catch (ErrorFoodException e){
            System.out.println(e.getMessage());
        }
    }
}
class People{
    String name;
    public People() {
    }
    public People(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void eat(Food food) throws ErrorFoodException{
        if ("粑粑".equals(food.foodName)){
            throw new ErrorFoodException("人不能吃"+food+"!");
            //System.out.println("sdsas"); 异常抛出后不能写任何代码,因为根本到不了,没有意义
        }
        //if 语句外就不受异常抛出的影响了,因为系统认为 if() 语句不一定执行,所以if()外的代码是有意义的
        System.out.println(name+"正在吃"+food);
    }
}
class Food{
    String foodName;
    public Food() {
    }
    public String getFoodName() {
        return foodName;
    }
    public void setFoodName(String foodName) {
        this.foodName = foodName;
    }
    public Food(String foodName) {
        this.foodName = foodName;
    }
    public String toString() {
        return foodName;
    }
}
class ErrorFoodException extends Exception{
    public ErrorFoodException() {
    }
    public ErrorFoodException(String message) {
        super(message);
    }
}

运行结果:
--------------------------------
人不能吃粑粑!

Process finished with exit code 0

枚举:

1)概念:枚举属于引用数据类型,当结果为两种情况的时候,用布尔型,当结果有3种或3种以上且可以一枚一枚将结果列举出来,就需要定义枚举来进行使用;

2)定义枚举:enum    枚举名   {     枚举值1,枚举值2,枚举值3,枚举值4,......      }

3)注意:每个枚举值都可以看作是一个常量,所以枚举值一般都用大写字母表示 ;

              目前版本的 JDK,switch 语句支持 int,String,枚举,但我们一般不这么使用枚举;

4)栗子老师:(此程序写的有些笨重,目的是为了更好的理解枚举)

import java.util.Random;
public class pra{
    public static void main(String[] args) {
        Random random=new Random();
        int i=random.nextInt(101);
        Result result=power(i);
        if (result==Result.S){
            System.out.println("危险等级:S");
        }else if (result==Result.A){
            System.out.println("危险等级:A");
        }else if (result==Result.B){
            System.out.println("危险等级:B");
        }else if (result==Result.C){
            System.out.println("危险等级:C");
        }else System.out.println("危险等级:D");
    }
    public static Result power(int i){
        if (i>=95){
            return Result.S;
        }else if (i<95&&i>=85){
            return Result.A;
        }else if (i<85&&i>=70){
            return Result.B;
        }else if (i<70&&i>=50){
            return Result.C;
        }else return Result.D;
    }
}
enum Result{
    S,A,B,C,D
}

运行结果:
------------------------------
危险等级:D

Process finished with exit code 0

随笔:

面试题:输出几?

 public class pra {
    public static void main(String[] args) {
        int Result=m();
        System.out.println(Result);
    }
    public static int m(){
        int i=100;
        try {
            return i;
        }finally {
            i++;
        }
    }
}
点击查看结果
100

Process finished with exit code 0

结果是不是很意外?为什么不是 101 呢?这里接触到了 java 中的语法规则(语法规则是 java 里优先级最高的,任何代码都必须遵循规则)

原则一:方法里中的代码必须遵循自上而下的顺序依次执行;

原则二:return 语句一旦执行,整个方法必须结束;

所以综合原则一与原则二,既然系统识别到了 return 语句就必须执行,但是结束方法之前,必须先执行 finally 中的“ i++ ”,虽然此时 i 的值确实等于 101 ,但是 return 要遵循原则一,不能输出新 i ,只能输出老 i = 100 ;

其实就像于:

int i=100;   
int j=i++;		//i 确实等于101
return j;       //但是系统*只能输出 j !!!

由于博主目前只是一只猿宝宝,所以有些地方可能说的有些片面,若前辈们能够指点一二就更好了      (~ ̄(OO) ̄)ブ

 

 

上一篇:Java 线程同步问题 synchronized


下一篇:Java 认识异常