枚举
枚举的基本定义和使用
枚举的定义
定义枚举类型, 需要使用到关键字 enum 。 枚举的名字是一个标识符, 遵循大驼峰命名法。
public enum Gender {
// 将这个枚举对象所有可能取到的值, 都列出来
// 枚举中的元素, 也是标识符, 遵循大驼峰命名法
Male, Female
}
public enum Month {
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
}
public enum Week {
Mon, Tue, Wed, Thu, Fri, Sat, Sun
}
枚举的使用
枚举是一种自定义的数据类型, 可以声明变量。 在使用的时候, 直接使用枚举类型.枚举值这样的形式进行枚举值的获取。
异常
异常的结构和分类
异常的结构
在Java中,用 Throwable 类来描述所有的不正常的情况。 Throwable 有两个子类:Exception 和 Error 。
Error: 描述发生在JVM虚拟机级别的错误信息, 这些错误无法被处理, 不做为现在的重点。
StackOverflowError: 栈溢出错误。
Exception: 描述程序遇到的异常。 异常是可以被捕获处理的, 是现在考虑的重点内容。
未经处理的异常,会导致程序无法进行编译或者运行。 因此在异常部分, 重点内容是:
异常该如何捕获处理。
Java中的异常的继承体系:
- 根类: Throwable
- 错误: Error
- 异常: Exception
- 运行时异常: RuntimeException
异常的分类
- 根据异常发生的位置
第一:普通的异常,会导致程序无法完成编译。 这样的异常被称为 – 编译时异常。 (Non-Runtime Exception: 非运行时异常, 但是由于异常是发生在编译时期的,因此,常常称为编译时异常。)
第二:Exception有一个子类-RuntimeException类, 在这个类中, 对异常进行了自动的处理。 这种异常不会影响程序的编译, 但是在运行中如果遇到了这种异常, 会导致程序执行的强制停止。 这样的异常被称为 – 运行时异常。
- 根据创建异常类的主体
第一:系统异常,系统提前定义好的,我们直接使用
第二:自定义异常,需要我们自己定义.
异常的工作原理
public class Demo7 {
public static void main(String[] args) {//4
Math math = new Math();
math.div(3,0);//3
}
}
class Math{
public int div(int a,int b){//2
return a/b;//1
}
}
- 1.在异常最初发生的位置创建一个异常的对象(new ArithmeticException()) 因为这里没有处理异常的能力,所以会将异常往上抛,抛给他所在的方法
- 2.div()方法也没有处理异常的能力,所以会继续往上抛,抛给调用这个方法的位置
- 3.调用div()方法的位置也没有处理异常的能力,所以会继续往上抛,抛给他所在的方法
- 4.main方法也没有处理异常的能力,所以会继续往上抛,抛给JVM,JVM会调用异常对象的打印方法,将异常信息打印到控制台
异常的特点
程序出现异常的时候,会打印异常的信息并中断程序,所以当有多个异常同时出现的时候,默认只能执行第一个.
异常的捕获处理
try-catch
try {
// 将可能出现异常的代码写到这里
// 如果这里的代码出现了异常, 从出现异常的位置开始, 到try代码段结束, 所有的代码不执行。
}
catch (异常类型 标识符) {//捕获异常
// 如果try中的代码出现了异常,并且异常的类型和catch的异常的类型是可以匹配上的,就会执行这里的逻辑
}
catch会对try里面的代码进行监听,如果try里面的代码没有发生异常,catch不会执行,会直接执行后面的代码.如果try里面的代码发生了异常,catch会立刻捕获(效果:try里面的代码会立刻中断,直接执行catch)
- 注意事项
catch中捕获的异常类型, 一定要和try中实际出现的异常类型一致。 否则将捕获不到异常,会导致try中实际出现的异常没有被捕获处理, 依然可以终止程序的编译或运行。
多个catch子句
如果在try代码段中, 出现了多种类型的异常, 此时如果需要对这些异常进行不同的处理,可以写多个catch子句。
在实际使用中:
- 如果要针对不同的异常,进行不同的处理,可以用多个catch。
- 如果要针对每一种异常,进行的处理方式相同,直接catch父类异常即可。
try{
//可能发生异常的代码
}catch(异常一 e){ //捕获异常 e就是要捕获的异常
//对当前异常的处理
}catch(异常二 e){ //捕获异常 e就是要捕获的异常
//对当前异常的处理
}catch(Exception e){ //捕获异常 e就是要捕获的异常
//对当前异常的处理
}
- 注意事项
多个catch书写的先后顺序, 对异常捕获有影响吗?
- 如果多个catch捕获的异常类型之间, 没有继承关系存在, 此时先后顺序无所谓。
- 如果多个catch捕获的异常类型之间, 存在继承关系, 则必须保证父类异常在后, 子类异
常在前。
finally子句
finally出现在try-catch子句的结尾, finally代码段中的内容, 始终会执行。
- 语法
try{
//可能发生异常的代码
}catch(Exception e){ //捕获异常 e就是要捕获的异常
//对当前异常的处理
}finally{
//必须执行的代码:主要用于资源的释放:比如关闭数据库,关闭流,关闭锁等
}
- 特点
无论try代码段中有没有异常出现,无论try里面出现的异常没有被捕获处理,finally中的代码
始终会执行。基于这个特点,常常在finally中进行资源释放、流的关闭等操作
- 作用范围
我们发现在catch中执行return后main方法结束,finally还能正常执行
catch中执行System.exit(0)后,程序退出,finally不能执行了
结论:只要当前的程序在运行,finally代码就能执行.
自定义异常
为什么要自定义异常
使用异常, 是为了处理一些重大的逻辑BUG。 这些逻辑BUG可能会导致程序的崩溃。 此
时, 可以使用异常机制, 强迫修改这个BUG。
系统中, 提供很多很多的异常类型。 但是, 异常类型提供的再多, 也无法满足我们所有的
需求。 当我们需要的异常类型, 系统没有提供的时候, 此时我们就需要自定义异常了。
如何自定义异常
其实,系统提供的每一种异常,都是一个类。所以,自定义异常,其实就是写一个自定义的
异常类。
-
如果要自定义一个编译时的异常,需要继承自 Exception 类。
- 特点:对异常进行处理的所有工作都要我们手动完成
-
如果要自定义一个运行时的异常,需要继承自 RuntimeException 类。
- 特点:所有的工作我们都可以不管
自定义的异常类, 理论上来讲, 类名可以任意定义。 但是出于规范, 一般都会以
Exception 作为结尾。
例如: ArrayIndexOutOfBoundsException、 NullPointerException、ArithmeticException…
常见的异常:订单异常 用户异常 负数异常
在重写方法中使用异常
注意点:
-
子类的同名方法中声明的异常等级要<=父类的.
-
如果子类同名方法声明了异常,父类必须声明异常.
-
父类抛出了异常,子类在重写方法的时候,可以不抛出异常
-
如果父类方法抛出的异常是 编译时异常
- 子类重写方法的时候,可以抛出相同的异常,或子类异常
-
子类重写方法的时候,可以抛出运行时异常
-
如果父类方法抛出的异常是 运行时异常
- 子类在重写的时候,可以是任意的运行时异常,不能是编译时异常