程式狂想筆記

一個攻城師奮鬥史

0%

Java 使用 Enum 小記

平常不怎麼使用 Enum ,非常地不熟悉,今天剛好用到,順便記錄一下。

簡單使用

1
2
3
public enum Action {
STOP, RIGHT, LEFT, UP, DOWN
}

這邊簡單可以看到

1
2
3
4
5
6
7
8
9
10
public static void play(int action) {
switch(action) {
case Action.STOP:
System.out.println("播放停止動畫");
break;
略...
default:
System.out.println("不支援此動作");
}
}

以前抄抄範例,這邊會發現int action
怎麼會跑出 int 出來?

其實 Enum 反編譯出來,會跟原本 Enum 出來不一樣
不知道這算不算是 Java 語法糖?

1
2
3
4
5
6
7
8
9
略...
static {
STOP = new Action("STOP", 0);
RIGHT = new Action("RIGHT", 1);
LEFT = new Action("LEFT", 2);
UP = new Action("UP", 3);
DOWN = new Action("DOWN", 4);
略...
}

詳細內容可以看:使用 enum 列舉常數

自定一些內容

我們公司使用不單是這樣
可以設定出

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
public enum Car {
MAX_CAR(100,"最高級車"), NORM_CAR(5,"中級車"), MIN_CAR(1,"低級車");

private int price;
private String desc;

private Car(int price, String desc) {
this.price = price;
this.desc = desc;
}

public int price() {
return price;
}

public String desc() {
return desc;
}

public static void main(String[] args) {
for(Car car : Car.values()) {
System.out.printf("Car(%s, %d, %s)%n",
car , car.price() , car.desc());
}
}
}

這邊看到會對印到 MAX_CAR(100,"最高級車"), NORM_CAR(5,"中級車"), MIN_CAR(1,"低級車");

1
2
3
4
private Car(int price, String desc) {
this.price = price;
this.desc = desc;
}

其他詳細可看:進階 enum 運用

取出列表資料(values)

1
2
3
for(Car car: Car.values())
System.out.println(car.name());
}

.values() 可以印出列表出來

那有沒有find 呢?
目前看應該只能用迴圈滾…

轉成陣列方法

You can do (pre-Java 8):

1
List<Enum> enumValues = Arrays.asList(Enum.values());

or
1
List<Enum> enumValues = new ArrayList<Enum>(EnumSet.allOf(Enum.class));

Using Java 8 features, you can map each constant to its name:
1
2
3
List<String> enumNames = Stream.of(Enum.values())
.map(Enum::name)
.collect(Collectors.toList());

Java: Check if enum contains a given string? - Stack Overflow

This should do it:

1
2
3
4
5
6
7
8
9
10
public static boolean contains(String test) {

for (Choice c : Choice.values()) {
if (c.name().equals(test)) {
return true;
}
}

return false;
}

This way means you do not have to worry about adding additional enum values later, they are > all checked.

Edit: If the enum is very large you could stick the values in a HashSet:

1
2
3
4
5
6
7
8
9
10
public static HashSet<String> getEnums() {

HashSet<String> values = new HashSet<String>();

for (Choice c : Choice.values()) {
values.add(c.name());
}

return values;
}

Then you can just do: values.contains(“your string”) which returns true or false.

values() 神奇 method 實作方法

參考: Java Enum - javatpoint
原理 static 放 $VALUES 陣列變數,使用values() 會傳 $VALUES 陣列變數 ,就可以 foreach 比較。

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
final class Season extends Enum  
{
public static Season[] values()
{
return (Season[])$VALUES.clone();
}
public static Season valueOf(String s)
{
return (Season)Enum.valueOf(Season, s);
}
private Season(String s, int i, int j)
{
super(s, i);
value = j;
}
public static final Season WINTER;
public static final Season SUMMER;
private int value;
private static final Season $VALUES[];
static
{
WINTER = new Season("WINTER", 0, 10);
SUMMER = new Season("SUMMER", 1, 20);
$VALUES = (new Season[] {
WINTER, SUMMER
});
}
}

其他之後有遇到再補

2020-06-18

特別載入環境變數方法

最近做 Enum 發現測試環境跟正式環境設定的值會不一樣,所以找一下有什麼方法可以解決這個問題。
目前這邊還沒測試能不能這樣用。

java property file as enum - Stack Overflow

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
public enum Constants {
PROP1,
PROP2;

private static final String PATH = "/constants.properties";

private static final Logger logger = LoggerFactory.getLogger(Constants.class);

private static Properties properties;

private String value;

private void init() {
if (properties == null) {
properties = new Properties();
try {
properties.load(Constants.class.getResourceAsStream(PATH));
}
catch (Exception e) {
logger.error("Unable to load " + PATH + " file from classpath.", e);
System.exit(1);
}
}
value = (String) properties.get(this.toString());
}

public String getValue() {
if (value == null) {
init();
}
return value;
}

}

enum 裡面帶 method 方法

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
//1.提供当前枚举类的对象,多个对象之间用逗号隔开,末尾对象分号结束
SPRING ("春天","春暖花开"){
@Override
public void show() {
System.out.println("spring!!!");
}
},
SUMMER("夏天","夏日炎炎"){
@Override
public void show() {
System.out.println("summer!!!");
}
},
AUTUMN ("秋天","秋高气爽"){
@Override
public void show() {
System.out.println("autumn!!!");
}
},
WINTER ("冬天","冰天雪地"){
@Override
public void show() {
super.show();
System.out.println("winter!!!");
}
};

參考: java枚举和注解 - 知乎

實用範例

方便以後直接找 sample code 來用,畢竟真的不常寫,很容易要想怎麼寫。
最佳範例: 菜鳥工程師 肉豬: Java 列舉(Enum)範例
還是推薦看裡面內容。

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
public enum WeekDay {

SUN("Sunday","星期日", 0),
MON("Monday","星期一", 1),
TUE("Tuesday","星期二", 2),
WED("Wednesday","星期三", 3),
THU("Thursday","星期四", 4),
FRI("Friday","星期五", 5),
SAT("Saturday","星期六", 6);

WeekDay(String day, String chinese, int code){
this.day = day;
this.chinese = chinese;
this.code = code;
}

private final String day;
private final String chinese;
private int code;

public static WeekDay getWeek(int i){
for(WeekDay weekDay : values()){
if(weekDay.getCode() == i) {
return weekDay;
}
}
return null;
}

public String getDay(){
return this.day;
}

public String getChinese() {
return this.chinese;
}

public int getCode() {
return this.code;
}

}