Java之枚举类和记录类
封面作者:千夜QYS3
兜兜转转还是决定恶补基础了,文章参考廖雪峰的java教程
枚举类
使用以及好处
- 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// enum
public class Main {
public static void main(String[] args) {
Weekday day = Weekday.SUN;
if (day == Weekday.SAT || day == Weekday.SUN) {
System.out.println("Work at home!");
} else {
System.out.println("Work at office!");
}
}
}
enum Weekday {
SUN, MON, TUE, WED, THU, FRI, SAT;
} - 好处:
enum常量本身带有类型信息,即Weekday.SUN类型是Weekday,编译器会自动检查出类型错误- 不可能引用到非枚举的值,因为无法通过编译。
- 不同类型的枚举不能互相比较或者赋值,因为类型不符。
enum的比较
两种方法,第一种更直接也更方便
1 | if (day == Weekday.FRI) { // ok! |
enum类型
引言
enum就是class,但是有以下几个特点:
- 定义的enum类型总是继承自java.lang.Enum,且无法被继承;
- 只能定义出enum的实例,而无法通过new操作符创建enum的实例;
- 定义的每个实例都是引用类型的唯一实例;
- 可以将enum类型用于switch语句。
枚举实例的一些方法
name()
返回常量名,例如:
1 | String s = Weekday.SUN.name(); // "SUN" |
ordinal()
- 返回定义的常量的顺序,从0开始计数,例如:
1
int n = Weekday.MON.ordinal(); // 1
- 改变枚举常量定义的顺序就会导致ordinal()返回值发生变化。例如: 所以如果在代码中编写了类似
1
2
3public enum Weekday {
SUN, MON, TUE, WED, THU, FRI, SAT;
}//这时候再同样输出就不是1了if(x.ordinal()==1)这样的语句,就要保证enum的枚举顺序不能变。新增的常量必须放在最后。 - 不要依靠
ordinal()的返回值,不小心修改了枚举的顺序编译器无法检查此类错误所以可以给每个枚举常量添加字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// enum
public class Main {
public static void main(String[] args) {
Weekday day = Weekday.SUN;
if (day.dayValue == 6 || day.dayValue == 0) {
System.out.println("Work at home!");
} else {
System.out.println("Work at office!");
}
}
}
enum Weekday {
MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6), SUN(0);
public final int dayValue;
private Weekday(int dayValue) {
this.dayValue = dayValue;
}
}- 注意:枚举类的字段也可以是非final类型,即可以在运行期修改,但是不推荐这样做!
- 判断枚举常量的名字,要始终使用
name()方法,绝不能调用toString()!- 默认情况下,对枚举常量调用
toString()会返回和name()一样的字符串。但是,toString()可以被覆写,而name()则不行。
- 默认情况下,对枚举常量调用
switch
- 枚举类可以应用在switch语句中。因为枚举类天生具有类型信息和有限个枚举常量,所以比int、String类型更适合用在switch语句中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// switch
public class Main {
public static void main(String[] args) {
Weekday day = Weekday.SUN;
switch(day) {
case MON:
case TUE:
case WED:
case THU:
case FRI:
System.out.println("Today is " + day + ". Work at office!");
break;
case SAT:
case SUN:
System.out.println("Today is " + day + ". Work at home!");
break;
default:
throw new RuntimeException("cannot process " + day);
}
}
}
enum Weekday {
MON, TUE, WED, THU, FRI, SAT, SUN;
}加上default语句,可以在漏写某个枚举常量时自动报错,从而及时发现错误。
记录类
使用record关键字
1 | record Point(int x, int y) {} |
等同于
1 | final class Point extends Record { |
除了用final修饰class以及每个字段外,编译器还自动为我们创建了构造方法,和字段名同名的方法,以及覆写toString()、equals()和hashCode()方法。
换句话说,使用record关键字,可以一行写出一个不变类。
和enum类似,我们自己不能直接从Record派生,只能通过record关键字由编译器实现继承。
构造方法
- 假设
Point类的x、y不允许负数,我们就得给Point的构造方法加上检查逻辑:1
2
3
4
5
6
7
8public record Point(int x, int y) {
public Point {
if (x < 0 || y < 0) {
throw new IllegalArgumentException();
}
}
} - 作为
record的Point仍然可以添加静态方法。一种常用的静态方法是of()方法,用来创建Point:1
2
3
4
5
6
7
8public record Point(int x, int y) {
public static Point of() {
return new Point(0, 0);
}
public static Point of(int x, int y) {
return new Point(x, y);
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Blog of Sof!
评论






