枚举、注解、异常处理
- 枚举
- 注解
- 异常
- 异常处理
1、枚举
分析下面问题:
要求创建 季节(Season)对象,设计并完成;
class Season {
private String name;
private String desc;//描述
public Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
//Getter and Setter
}
使用上述对象是不合理的
Season对象有以下特点:
- 季节的值是有限的几个值(spring、summer、autumn、winter)
- 只读、不修改
1.1 解决方案-使用枚举:
- 枚举对应英文(enumeration,简写 enum)
- 枚举是一组常量的集合
- 可以理解为:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。
1.2 实现方式
-
自定义类实现枚举
/** * * 自定义类实现枚举 */ public class Enumeration01 { public static void main(String[] args) { System.out.println(Season.AUTUMN); } } class Season { private String name; private String desc;//描述 public static final Season SPRING = new Season("春天","温暖"); public static final Season WINTER = new Season("冬天","寒冷"); public static final Season SUMMER = new Season("夏天","炎热"); public static final Season AUTUMN = new Season("秋天","凉爽"); //1.将构造器私有化,防止直接new //2.去掉setter方法,防止属性被修改 //3.在Season内部,直接创建固定的对象 private Season(String name, String desc) { this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } }
-
使用enum关键字实现枚举
enum Season2 { SPRING("春天","温暖"),WINTER("冬天","寒冷"),SUMMER("夏天","炎热"),AUTUMN("秋天","凉爽"); /** * 名字 */ private String name; /** * 描述 */ private String desc; /* 1.使用 enum 关键字 替代 class 2.SPRING("春天","温暖")替代 public static final Season SPRING = new Season("春天","温暖"); 3.在Season内部,直接创建固定的对象 4.如果有多个(常量对象),使用逗号间隔 5.定义常量,要写在前面 */ private Season2(String name, String desc) { this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } }
使用细节:
- enum关键字标注的枚举类,默认会继承Enum类,而且是一个final类【可以使用javap反编译】
- 传统的 public static final Season2 SPRING = new Season2(“春天”,“'温暖”);简化成SPRING(”春天",“温暖");
- 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
- 当有多个枚举对象时,使用逗号间隔,最后一个分号结尾
- 枚举对象必须放在枚举类的行首
//下面代码成立
enum Gender{
BOY,Girl;//会调用无参构造器
}
1.3 Enum类的常用方法
- toString():Enum类已经重写过了,返回的是当前对象名,子类可以重写该方法,用于返回对象的属性信息
- final name():返回当前对象名(常量名),子类不能重写
- ordinal():输出的是该枚举对象的次序/编号
- values():返回定义的所有枚举对象数组;
- valueOf():将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
- compareTo():比较两个枚举常量,比较的就是位置号
1.4 enum实现接口
-
使用enum关键字后,就不能再继承其他的类了,因为enum会隐式继承Enum类,而Java是单继承
-
枚举类和普通类一样,可实现接口:
enum 类名 implements 接口1,接口2{ }
2、注解
注解(Annotation) 也被称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。
和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等。
1.1 基本介绍
使用Annotation时要在其前面增加@符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素
三个基本的Annotation:
- @Override:限定某个方法,是重写父类方法,该注解只能用于方法
- @Deprecated:用于表示某个程序元素(类,方法等)已过时
- @SuppressWarnings:抑制编译器警告
- @Target(ElementType.METHOD),说明只能修饰
方法 - @Target是修饰注解的注解,称为元注解
1.2 JDK的元注解
基本介绍:
JDK的元注解用于修饰其他注解
元注解的种类:
- Retention:指定注解的作用范围,三种 SOURCE.CLASS,RUNTIME2)
- Target :指定注解可以在哪些地方使用
- Documented :指定该注解是否会在javadoc体现
- Inherited :子类会继承父类注解
3、异常
基本概念:
Java语言中,将程序执行中发生的不正常情况称为 “ 异常 ”。(开发中的语法错误和逻辑错误不是异常)
异常事件可分为两大类:
- Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如: StackOverflowError[栈溢出]和OOM(out of
memory). Error是严重错误,程序会崩溃。 - Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,
3.1 Exception 分为两大类:
- 运行时异常
- 运行时异常,编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常
- 编译时异常
- 是编译器要求必须处理的异常
异常类结构图:
3.1.1 常见的运行时异常
- NUllPointException空指针异常
- ArithmeticException数学运算异常、
- ArrayIndexOutOfException数组小标越界异常
- ClassCastException类型转换异常
- NumberFormatException数字格式不正确异常
3.1.2编译异常
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译
常见的编译异常
- SQLException // 操作数据库时,查询表可能发生异常
- IOException //操作文件时,发生的异常
- FileNotException //当操作一个不存在的文件时,发生异常
- ClassNotFoundEXception //加载类,而该类不存在时,异常
- EOFException //操作文件,到文件末尾,发生异常
- IllegalArguementException //参数异常
4、异常处理
异常处理就是当异常发生时,对异常处理的方式。
两种方式:
-
try-catch-finally
程序员在代码中捕获发生的异常,自行处理
-
throws
将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM
4.1 try-catch-finally:
try {
代码...
可能会有异常
}catch(Exception e){
//捕获到异常
//1.当异常发生时
//2.系统将异常封装成Exception 对象e,传递给catch
//3.得到异常对象后,程序员自己处理
//注意:如果没有发生异常catch代码块不执行
}finally{
//1.不管try代码块是否有异常发生,始终要执行finally
//2.所有,通常将释放资源的代码,放在finally
}
-
如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
-
如果异常没有发生,则顺序执行try的代码块,不会进入到catch.
-
如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码- finally { }
-
可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch,案例演示
-
可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
try { //代码... }finally{ //总是执行 }
4.2 throws:
使用细节:
- 对于编译异常,程序中必须进行处理,比如try-catch 或者 throws
- 对于运行时异常,程序中如果没有处理,默认就是throws的方式**(有默认处理)**
- 子类重写父类 方法时:子类方法抛出的异常要与父类方法抛出异常相同或者是其子类
- 在throws过程中,如果有方法try-catch,就相当于处理异常,就可不必throws
向上传递异常给JVM后,JVM会先打印异常信息,再退出程序
如果程序员,没有显示的处理异常,默认是throws
4.3 自定义异常
当程序中出现了某些 “ 错误 ”,但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。
public class BusinessException extends RuntimeException{}
//通过throw抛出自定义异常
throw new BusinessException();
一般自定义异常继承运行时异常,好处是不用显式的处理自定义异常
4.4 throw和throws 的区别
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |
出自定义异常
throw new BusinessException();
一般自定义异常继承运行时异常,好处是不用显式的处理自定义异常