day10_异常处理&枚举

异常处理&枚举

学习目标:

1. 熟练掌握java的异常处理机制
2. 熟练掌握枚举数据类型

视频链接:https://www.bilibili.com/video/BV1vr4y177uu?spm_id_from=333.999.0.0&vd_source=c674caf7b33c72dc23df379819432644

一、异常处理

1.1 什么是异常?

在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是否始终保持 通畅等等。

异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误不是异常)

1.2 java的异常体系

java的异常体系如下:

在这里插入图片描述

Throwable是异常体系的根类,提供了大量的异常处理方法,子类有Exception和Error,各自含义如下:

  • Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError 一般不编写异常处理代码,程序员应该从程序的逻辑上尽量避免这种情况。

  • Exception: 因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理;Exception异常又分为编译时异常和运行时异常

    • 编译时异常:既在编译阶段出现的异常,是指程序员必须处理的异常,否则会对程序产生难以意料的后果;对于这类异常要求程序员必须进行异常处理或者异常抛出。

    • 运行时异常:是指在编译阶段不报异常,在运行阶段报出的异常;这类异常一般是指编程时的逻辑错误,如数组越界异常,空指针异常等,这时候要求程序员从编程逻辑上避免这些问题。当然也有一些不是程序编程引起的运行时异常,如算术异常分母为0,而分母是客户输入的,那么这个异常就不是程序员编程引起的运行时异常,需要异常处理。

1.3 常见异常介绍

常见的运行时异常有:

  • java.lang.RuntimeException
    • ClassCastException
    • ArrayIndexOutOfBoundsException
    • NullPointerException
    • ArithmeticException

常见的编译时异常有:

  • java.io.IOExeption
    • FileNotFoundException

1.4 异常处理 throws

在定义方法的过程中,方法体的语句可能出现某种异常,但是并不能确定如何处理这种异常,则方法应显示的声明抛出异常,表明该方法可能出现这些异常,但是没有做出处理,交给方法的调用者处理。

在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

示例1:定义数学类并指出可能出现的异常

//1.定义接口
public interface MyMath{
	//1.定义除法规范 告诉实现者可能出现异常
	public int div(int i,int j) throws Exception;
}
//2.定义数学类类
class MyMathImpl implements MyMath{

	@Override // 3.定义数学类 是给别人用的告诉调用者有风险。
	public  int div(int i, int j) throws Exception {
		return i/j;
	}
	
}

注意: 子类抛出的异常不能大于父类异常

1.5 异常处理try … catch … finally

在调用有异常的方法时,我们可根据是否出现异常状况做出相应的异常处理,语法如下:

在这里插入图片描述

示例:对上述的数学类中方法调用,并处理异常

public interface MyMath{
    //1.定义除法规范 告诉实现者可能出现异常
    public int div(int i,int j) throws Exception;

    /*程序入口*/
    public static void main(String[] args) {
        //创建对象
        MyMath myMath = new MyMathImpl();
        try {
            //可能出现异常的代码
            myMath.div(1,0);
        } catch (Exception e) {
            //出现异常运行的代码
            e.printStackTrace();
        } finally {
            //一定会执行的代码
            System.out.println("最要要执行的代码");
        }
    }
}
//2.定义数学类类
class MyMathImpl implements MyMath{

    @Override // 3.定义数学类 是给别人用的告诉调用者有风险。
    public  int div(int i, int j) throws Exception {
        return i/j;
    }

}

1.6 手动抛出异常 throw

Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要使用人工创建并抛出;手动抛出的异常必须是Throwable或其子类的实例。

示例1:手动抛出异常

/**
 * 手动抛出异常
 */
public class ThrowDemo {
    //定义一个工资校验方法,工资不能为负数
    public static int sal(int sal) throws Exception{
        //工资是负数报异常
        if(sal<0) {
            //3.创建一个Throwable 子类异常
            Exception exception = new Exception("工资不能是负数");
            //RuntimeException exception = new RuntimeException("工资不能是负数");
            //4. 手动抛出异常
            throw exception;
        }
        return sal;
    }

    public static void main(String[] args) {
        try {
            sal(-5);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
}

1.7 自定义异常

自定义异常类过程如下:

  1. 一般地,用户自定义异常类都是RuntimeException的子类。
  2. 自定义异常类通常需要编写几个重载的构造器。
  3. 自定义异常需要提供serialVersionUID

如何使用自定义异常:

  1. 自定义的异常通过throw抛出。
  2. 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型

示例1:自定义负数异常

public class FuShuException extends RuntimeException {
	
	private static final long serialVersionUID = 1L;
	public FuShuException() {
	}
	public FuShuException(String message) {
		super(message);
	}
}
public class FuShuExceptionTest {
	public static double getSalary(double money) {
		if(money<0) {
			throw new FuShuException("工资不能为负数");
		}
		return money;
	}
	public static void main(String[] args) {
		getSalary(-10);
	}
}

1.8 小结

  1. java的异常系统

  2. 异常处理机制throws与try … catch … finally

  3. 编译时异常和运行时异常的区别

  4. 手动抛出异常throw

  5. 自定义异常

二、枚举

2.1 枚举入门案例

JDK5中才出现枚举技术,并独立出关键字Enum

什么是枚举? 枚举就是一一列举固定值;例如:季节只能用春、夏、秋、冬;再比如月份1-12月;在比如星期1-7。

为什么需要枚举数据类型? 我们发现开发中往往有这么一类需求:需要一一列举某几个固定值情况,不能超出这几个固定值范围。

示例1:学生等级

/**
 * 需求:学生类的成绩等级只能是A、B、C
 */
public class Student {
    private String name;
    private String grade;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade)  {
        if(grade.equals("A") || grade.equals("B") || grade.equals("C")){
            this.grade = grade;
        }else {
            throw new RuntimeException("不是合法的等级");
        }

    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", grade='" + grade + '\'' +
                '}';
    }

    public static void main(String[] args) {
        Student xiaoMing = new Student();
        xiaoMing.setGrade("D");
        xiaoMing.setName("小明");
        System.out.println(xiaoMing);
    }
}

类似上面的问题可以使用枚举技术解决

**枚举:类的对象只有有限个,确定的。举例如下: **

  • 星期:Monday(星期一)、…、Sunday(星期天)
  • 季节:Spring(春节)…Winter(冬天)
  • 线程状态:创建、就绪、运行、阻塞、死亡

枚举类的实现JDK5之前需要自定义枚举类 ;JDK5 新增的 enum 关键字用于定义枚举类

2.2 手动实现枚举

如何手动实现枚举类?

  1. 私有化类的构造器,保证不能在类的外部创建其对象
  2. 在类的内部创建枚举类的实例。声明为:public static final

示例1:自定义等级枚举,并应用

public class Student {
    private String name;
    private Grade grade;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }

    public static void main(String[] args) {
        Student xiaoMing = new Student();
        xiaoMing.setName("小明");
        xiaoMing.setGrade(Grade.A);
        System.out.println(xiaoMing);
    }
}
//自定义枚举类
class Grade{
    //1.私有构造器
    private Grade(){

    }
    //2.公有静态常亮枚举实例
    public static final Grade A = new Grade();
    public static final Grade B = new Grade();
    public static final Grade C = new Grade();
}

2.3 使用enum定义枚举

使用 enum定义的枚举类默认继承了 java.lang.Enum类,因此不能再继承其他类

  • 枚举类的构造器只能使用 private 权限修饰符
  • 枚举类的所有实例必须在枚举类中显式列出(, 分隔; 结尾)。列出的实例系统会自动添加 public static final 修饰
  • 必须在枚举类的第一行声明枚举类对象

示例1:使用enum定义枚举

public enum Grade {
	/*A(),B(),C(); 全写模式*/
	A,B,C; //简写模式
}
//测试使用
public class Student {
	private String name;
	private Grade grade;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Grade getGrade() {
		return grade;
	}
	public void setGrade(Grade grade) {
		this.grade = grade;
	}
	
	@Override
	public String toString() {
		return "Student [name=" + name + ", grade=" + grade + "]";
	}
	public static void main(String[] args) {
		Student anqila = new Student();
		anqila.setGrade(Grade.A);
		anqila.setName("安其拉");
		System.out.println(anqila);
	}
}

示例2:定义构造器有参数的枚举

public enum Grade {
    //3.定义枚举固定值
    A("85-100"),B("75-84"),C("60-74");
    //1.定义属性
    private String score;
    //2.通过构造方法赋值
    private Grade(String score){
        this.score = score;
    }
    //4.可以给枚举类的属性添加getter和setter方法
    public String getScore() {
        return score;
    }

    public void setScore(String score) {
        this.score = score;
    }
}
public class Student {
    private String name;
    private Grade grade;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }

    public static void main(String[] args) {
        Student xiaoMing = new Student();
        xiaoMing.setName("小明");
        xiaoMing.setGrade(Grade.A);
        System.out.println(xiaoMing);
        System.out.println(Grade.A.getScore());
    }
}

和普通 Java 类一样,枚举类可以实现一个或多个接口。若每个枚举值在调用实现的接口方法呈现相同的行为方式,则只要统一实现该方法即可。 若需要每个枚举值在调用实现的接口方法呈现出不同的行为方式, 则可以让每个枚举值分别来实现该方法。

示例3:实现接口的枚举定义与使用

//1.定义接口
interface GradeInter{
    public abstract String getStr();
}
//2.枚举是特殊的类可以实现接口
public enum Grade implements GradeInter{
   //A("85-100"),B("75-84"),C("60-74");
    A("85-100"){
        @Override
        public String getStr() {
            return "优秀";
        }
    },
    B("75-84"){
        @Override
        public String getStr() {
            return "良好";
        }
    },
    C("60-74"){
        @Override
        public String getStr() {
            return "及格";
        }
    };

    //定义属性
    private String score;
    //定义私有构造器
    private Grade5(String score){this.score=score;}
    //统一实现抽象方法

   /* @Override
    public String getStr() {
        return "考试通过";
    }*/

    public String getScore() {
        return score;
    }

    public void setScore(String score) {
        this.score = score;
    }
}

public class Student {
    private String name;
    private Grade grade;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }

    public static void main(String[] args) {
        Student xiaoMing = new Student();
        xiaoMing.setName("小明");
        xiaoMing.setGrade(Grade.A);
        //1.查看A等级的分数
        System.out.println(Grade.A.getScore());
        //2.查看A等级的描述情况
        System.out.println(Grade.A.getStr());
    }
}

2.4 枚举在switch结构中应用

JDK5 中可以在 switch 表达式中使用enum定义的枚举类的对象作为表达式, case 子句可以直接使用枚举值的名字, 无需添加枚举类作为限定。

示例1:在switch中使用季节枚举

public enum Season {
    //1.春季、夏季、秋季、冬季、
    SPRINGTIME,SUMMER,AUTUMN,WINTER;
}
public class SeasonDemo {
    public static void main(String[] args) {
        switch(Season.SPRINGTIME){
            case SPRINGTIME:
            System.out.println("春天");
            break;
            case SUMMER :
            System.out.println("夏天");
            break;
            case AUTUMN :
            System.out.println("秋天");
            break;
            case WINTER :
            System.out.println("冬天");
            break;
        }
    }
}

2.5 枚举的常用方法

枚举的常用方法如下:

在这里插入图片描述

示例1:枚举的常用方法

public class EnumMethod {
    //1.枚举常用方法
    public static void main(String[] args) {
        //1.获得枚举名字
        String name = Grade.A.name();
        System.out.println(name);
        //2.将字符串的枚举名字转为枚举值
        Grade a = Grade.valueOf("A");
        System.out.println(a);
        //3.返回枚举值所在数组中的下标值
        int index = Grade.B.ordinal();
        System.out.println(index);
        //4.返回枚举实例的数组容器
        Grade[] values = Grade.values();
        for(int i=0;i<values.length;i++){
            System.out.println(values[i]);
        }
    }
}

2.6 小结

  • 枚举是一种特殊的类, 枚举类 。
  • 使用enum定义的枚举默认继承了java.lang.Enum。所以可以直接使用父类Enum的方法。
  • 枚举声明的每一个枚举值 都是静态常量。
  • 枚举可以实现接口,可以统一实现抽象方法,也可以单独实现抽象方法
  • jdk5以后 switch 支持枚举。

三、总结

  1. 异常体系
  2. 异常处理 throws
  3. 异常处理try … catch … finally
  4. 手动抛出异常 throw
  5. 自定义异常
  6. 枚举的基本使用
  7. 枚举实现接口
  8. 枚举常用方法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值