Java笔记——枚举注解异常
枚举
创建Season对象有如下特点: 1. 季节的值是有限的几个值(spring, summer, autumn, winter)
- 只读,不需要修改
解决方案: 1. 枚举对应英文(enumeration,简写enum)
枚举是一组常量的集合
可以理解为:枚举属于一种特殊的类,里面只包含一组有限的特定对象
枚举的两种实现方式
自定义类实现枚举
- 不需要提供
setXxx方法,因为枚举对象通常为只读 - 对枚举对象/属性使用
final+static共同修饰,实现底层优化 - 枚举对象通常使用全部大写,常量的命名规范
- 枚举对象根据需要,可以有多个属性
小结:进行自定义类实现枚举,有如下特点:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package com.company.enum_;
public class Enumeration {
public static void main(String[] args) {
System.out.println(Season.SPRING);
}
}
class Season {
private String name;
private String desc;
public final static Season SPRING = new Season("春天", "温暖");
public final static Season SUMMER = new Season("夏天", "炎热");
public final static Season AUTUMN = new Season("秋天", "凉爽");
public final static Season WINTER = new Season("冬天", "寒冷");
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
} - 构造器私有
- 本类内部创建一组对象
- 对外暴露对象(通过为对象添加
public final static修饰符) - 可以提供
get方法,但是不要提供set方法
使用 enum 关键字实现枚举
1 | |
注意事项
- 当使用
enum关键字开发一个枚举类时,默认会继承Enum类 (javap反编译)
- 传统的
public static final Season SPRING = new Season("春天", "温暖");简化成SPRING("春天", "温暖"), 这里需清楚它调用的是哪个构造器 - 如果无参构造器 创建 枚举对象,则实参列表和小括号都可以省略
- 当有多个枚举对象时,使用
,间隔,最后有一个分号结尾 - 枚举对象必须放在枚举类的行首
enum常用方法
使用关键字 enum 时,会隐式继承 Enum 类,因此可以使用
Enum 类相关方法 1
2public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serialization {
}
| 方法名 | 详细描述 |
|---|---|
| valueOf | 传递枚举类型的Class对象和枚举常量名称给静态方法valueOf,会得到与参数匹配的枚举常量。 |
| toString | 得到当前枚举常f的名称。你可以通过重写这个方法来使得到的结果更易读。 |
| equals | 在枚举类型中可以直接使用 "==" 来比较两个枚举常量是否相等。Enum提供的这个equals()方法,也是直接使用 "==" 实现的。它的存在是为了在Set、List和Map中使用。注意,equals()是不可变的。 |
| hashCode | Enum 实现了hashCode()来和equals()保持一致。它也是不可变的。 |
| getDeclaringClass | 得到枚举常量所属枚举类型的Class对象。可以用它来判断两个枚举常量是否属于同一个枚举类型。 |
| name | 得到当前枚举常量的名称。建议优先使用toString()。 |
| ordinal | 得到当前枚举常量的次序。(从0开始编号) |
| compareTo | 枚举类型实现了Comparable接口,这样可以比较两个枚举常量的大小(按照声明的顺序排列) |
| clone | 枚举类型不能被Clone。为了防止子类实现克隆方法,Enum实现了一个仅抛出CloneNotSupportedException异常的不变Clone()。 |
| values | 返回当前枚举类中所有的常量, 用对象数组接收 |
enum 实现接口
- 使用enum关键字后,就不能继承其它类了,因为enum会隐式继承Enum,而Java时单继承机制。
- 枚举类和普通类一样,可以实现接口
1
enum 类名 implements 接口1, 接口2 {}
注解
注解的理解
- 注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。
- 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
- 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和xml配置等。
基本的 Annotation 介绍
使用Annotation时要在其前面增加@符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素
三个基本的Annotation:
@Override: 限定某个方法,是重写父类方法,该注解只能用于方法@Deprecated: 用于表示某个程序元素(类,方法等)已过时@SuppressWarnings: 抑制编译器警告 ({"all"})
补充说明:
@interface不是interface,是注解类,是jdk5.0之后加入的
1
2
3
4@Target(ElementType.METHOD) // 修饰注解的注解
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
四种元注解
Retention//指定注解的作用范围,三种SOURCE,CLASS,RUNTIMETarget//指定注解可以在哪些地方使用Documented//指定该注解是否会在javadoc体现Inherited//子类会继承父类注解
异常
异常基本介绍
基本概念 Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
执行过程中所发生的异常事件可分为两类
- Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如: StackOverflowError[栈溢出]和OOM(out of memory), Error是严重错误,程序会崩溃。
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常和编译时异常。
异常体系图
- 体现了继承和实现关系

编译异常: Java源程序 -> 字节码文件 运行异常: 字节码文件 -> 在内存种加载、运行类
异常体系图的小结
- 异常分为两大类,运行时异常和编译时异常;
- 运行时异常,编译器检测不出。一般是指编程时的逻辑错误,是
程序员应该避免其出现的异常。
java.lang.RuntimeException类及它的子类都是运行时异常; - 对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程 序的可读性和运行效率产生影响;
- 编译时异常,是编译器要求必须处置的异常。
常见的运行时异常
NullPointerException空指针异常ArithmeticException数据运算异常ArrayIndexOutOfBoundsException数组下标越界异常ClassCastException类型转换异常 当试图将对象强制转换为不是实例的子类时,抛出该异常NumberFormatException数据格式不正确异常
常见的编译时异常
SQLException操作数据库时,查询表可能发生的异常IOException操作文件时,发生的异常FileNotFoundException当操作一个不存在的文件时,发生异常ClassNotFoundException加载一个不存在的类时,发生的异常EOFException操作文件,到文件末尾,发生异常IllegalArguementException参数异常
异常处理
基本介绍
异常处理就是当异常发生时,对异常处理的方式。 ### 异常处理的方式
1)try-catch-finally 程序员在代码种捕获发生的异常,自行处理
1
2
3
4
5
6
7
8
9
10
11try {
// 可能有有异常的代码
} catch(Exception e) {
// 捕获到异常
// 当异常发生时,系统将异常封装成Exception对象e,传递给catch
// 得到异常后,程序员自己处理
// 若没有发生异常则catch代码块不执行
} finally {
// 1. 不管try代码块是否有异常发生,始终要执行finally
// 2. 通常将释放资源的代码放在这里
}throws
将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM,输出异常信息,退出程序

try - catch 注意事项
快捷键:ctrl + alt + t 1.
如果异常发生,则异常发生后面的代码不会执行,直接进入到catch块 2.
如果异常没有发生,则顺序执行try的代码块,不会进入到catch 3.
如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用finally
4.
可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch
5. 可以进行 try - finally
配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑。
1
2
3
4
5
6
7
8
9try {
String str = "123";
int a = Integer.parseInt(str);
System.out.println("数字:" + a);
} catch (NumberFormatException e) {
System.out.println("异常信息 = " + e.getMessage());
}
System.out.println("程序继续执行...");
练习1
1 | |
练习2
循环输入,直到是整数为止 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Exception01 {
public static void method() {
Scanner scanner = new Scanner(System.in);
int num = 0;
while (true) {
System.out.println("请输入一个整数:");
try {
num = Integer.parseInt(scanner.next());
break; } catch (NumberFormatException e) {
System.out.println("非法输入,请重试!");
}
}
System.out.println("输入的值为:" + num);
}
public static void main(String[] args) {
method();
}
}
throws 异常处理
1)如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法地调用者负责处理;
2)在方法声明中用throws语句可以声明抛出异常地列表,throws后面地异常类型可以是方法中产生地异常类型,也可以是该异常的父类;
1
2
3
4
5
6public static readFile(String file) throws FileNotFoundException {
// ...
// 读取文件的操作可能产生FileNotFoundException类型的异常
FileInputStream fis = new FileInputStream("./tmp.txt");
// ...
}try-catch 或者 throws
2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
4)在throws 过程中,如果有方法 try - catch
,就相当于处理异常,此时就不必 throws 1
2
3
4
5
6
7
8
9public static void f1() {
f2(); // 报错
// f2()抛出编译异常,f1()调用就要处理它的异常
// 要么 throws 抛出, 要么 try-catch
}
public static void f2() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("./tmp.txt");
}Exception或者RuntimeException
2. 如果继承Exception,属于编译异常 3.
如果继承RuntimeException,属于运行异常(最常见)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class CustomException {
public static void main(String[] args) {
int age = 180;
if (!(age >= 18 && age <= 120)) {
throw new AgeException("年龄需要在18 ~ 120之间");
}
System.out.println("输入正确");
}
}
class AgeException extends RuntimeException {
public AgeException(String message) { // 构造器
super(message);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class ReturnExceptionDemo {
static void methodA() {
try {
System.out.println("1. 进入方法A");
throw new RuntimeException("3. 制造异常");
} finally {
System.out.println("2. 用A方法的finally");
}
}
static void methodB() {
try {
System.out.println("4. 进入方法B");
return; } finally {
System.out.println("5. 调用B方法的finally");
}
}
}
public static void main(String[] args) {
try {
ReturnExceptionDemo.methodA();
} catch (Exception e) {
System.out.println(e.getMessage());
}
ReturnExceptionDemo.methodB();
}