Java中的一些有趣的内容

enum

enum也就是Java中的枚举类,我们可以声明一个类为如下的几个具体类型:

  • class
  • interface
  • enum
  • annotation(@interface)

那么enum中可以进行什么操作,enum是怎么实现的?

enum通常可以进行的操作

通常我们会拿它来定义一些枚举值,比如

虽然我很想翻出几个java中自带的enum但是想了几个都是static final XXX什么的

还是随便来一个吧

1
2
3
public enum Color {
GREEN, YELLOW, BLUE
}

也就是定义一些常量,然后我们可以给它们加一点属性…

1
2
3
4
5
6
7
8
9
10
11
public enum Color {
GREEN("绿色", "#00ff00"), RED("红色", "#ff0000"), BLUE("蓝色", "0000ff");

Color(String description, String value) {
this.description = description;
this.value = value;
}

public String description;
public String value;
}

再加一点方法…

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
38
39
40
41
42
43
44
45
46
public enum Color {
GREEN("绿色", 0, 255, 0) {
@Override
public int getChannelValue(String original) {
return Integer.parseInt(original.substring(3, 5), 16);
}
},
RED("红色", 255, 0, 0) {
@Override
public int getChannelValue(String original) {
return Integer.parseInt(original.substring(1, 3), 16);
}
},
BLUE("蓝色", 0, 0, 255) {
@Override
public int getChannelValue(String original) {
return Integer.parseInt(original.substring(5, 7), 16);
}
};

Color(String description, int r, int g, int b) {
this.description = description;
this.r = r;
this.g = g;
this.b = b;
}

public String description;
public int r;
public int g;
public int b;

public String getValue() {
return "#" + toHexString(r) + toHexString(g) + toHexString(b);
}

private String toHexString(int i) {
String hex = Integer.toHexString(i);
if (hex.length() == 1) {
hex = "0" + hex;
}
return hex;
}

public abstract int getChannelValue(String original);
}

我们可以在里面放一些

  • 属性
  • 普通方法
  • 抽象方法
  • 构造函数

如果是构造函数或者是抽象方法,我们需要在每一个枚举值中进行重载,也就是下面这个写法:

1
2
3
4
5
6
BLUE("蓝色", 0, 0, 255) {
@Override
public int getChannelValue(String original) {
return Integer.parseInt(original.substring(5, 7), 16);
}
};

看起来就像实现一个匿名内部类一样(其实实际上也是的)

实现原理

我们操作完上面的步骤,现在看看它是怎么实现的

实际上enum在Java1.5开始才加入Java中,我们定义的枚举类和里面的枚举值实际上是继承了java.lang.Enum的类和它的匿名内部类的实现。

enum XXX实际上是abstract class XXX extends Enum<XXX>

而里面的每一个枚举值A,B,C是这个类的几个static final实例。

由于XXX是抽象类,所以每一个实例初始化都需要override构造方法和抽象方法,来实现一个匿名内部类,每一个枚举值都是抽象类里面的不同匿名内部类的实例。

这样就可以达到一个枚举的效果。

LocalDateTime

@since 1.8
java.time.LocalDateTime是Java8开始加入的类。

操作起来应该比较舒服了。

此外LocalDateTime是与时区无关的,它不能单独表示某一个确切的时间点。

(我们在数据库里存的DateTime呢)

最大和最小值

LocalDateTime.MINLocalDateTime.MAX可以表示-999999999-01-01T00:00:00和+999999999-12-31T23:59:59.999999999。

也就是说如果使用LocalDateTime, 几乎没有需要担心有时间表示不了的情况。

一些方法

LocalDateTime实际上是由LocalDate和LocalTime组成的。

可以用now(), of()等方法构造一个LocalDateTime

而LocalDateTime对象可以使用各种minus, plus方法来获得另一个时间,当然也可以使用with某个value的方法。

也就是说如果我们需要获得上一周时间,上一周开始时间,等等,都是可以很方便地操作的

这些方法的返回值是一个新的LocalDateTime对象,所以我们可以…..调用来拿到我们想要的时间。

(不过还是JodaTime的方便一些)

LocalDate和LocalTime

LocalTime中的每一个field都是用一个单独的int来存储的。

(这个实现一点都不复杂)

收集一些待解决的问题

  1. Java里面声明一个数字的时候可以用下划线分隔… 如123_123_123
  2. 所以不写访问权限的时候是可以从哪里访问来着…
  3. Objects.requireNonNull();似乎是用来抛出异常的